FEMRepresentationUtility.m 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. //
  2. // Created by zen on 12/05/15.
  3. // Copyright (c) 2015 Yalantis. All rights reserved.
  4. //
  5. #import "FEMRepresentationUtility.h"
  6. #import "FEMMapping.h"
  7. #import "FEMMappingUtility.h"
  8. #import "FEMAttribute.h"
  9. id FEMRepresentationRootForKeyPath(id representation, NSString *keyPath) {
  10. if (keyPath.length > 0) {
  11. return [representation valueForKeyPath:keyPath];
  12. }
  13. return representation;
  14. }
  15. void _FEMRepresentationCollectPresentedPrimaryKeys(id, FEMMapping *, NSDictionary *);
  16. void _FEMRepresentationCollectObjectPrimaryKeys(NSDictionary *object, FEMMapping *mapping, NSDictionary *container) {
  17. if (mapping.primaryKey) {
  18. FEMAttribute *primaryKeyMapping = mapping.primaryKeyAttribute;
  19. id primaryKeyValue = FEMRepresentationValueForAttribute(object, primaryKeyMapping);
  20. if (primaryKeyValue && primaryKeyValue != NSNull.null) {
  21. NSMutableSet *set = container[mapping.entityName];
  22. [set addObject:primaryKeyValue];
  23. }
  24. }
  25. for (FEMRelationship *relationship in mapping.relationships) {
  26. id relationshipRepresentation = FEMRepresentationRootForKeyPath(object, relationship.keyPath);
  27. if (relationshipRepresentation && relationshipRepresentation != NSNull.null) {
  28. _FEMRepresentationCollectPresentedPrimaryKeys(relationshipRepresentation, relationship.mapping, container);
  29. }
  30. }
  31. }
  32. void _FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping, NSDictionary *container) {
  33. if ([representation isKindOfClass:NSArray.class]) {
  34. for (id object in (id<NSFastEnumeration>)representation) {
  35. _FEMRepresentationCollectObjectPrimaryKeys(object, mapping, container);
  36. }
  37. } else if ([representation isKindOfClass:NSDictionary.class] || [representation isKindOfClass:[NSNumber class]] || [representation isKindOfClass:[NSString class]]) {
  38. _FEMRepresentationCollectObjectPrimaryKeys(representation, mapping, container);
  39. } else {
  40. NSCAssert(
  41. NO,
  42. @"Expected container classes: NSArray, NSDictionary, NSNumber or NSString. Got:%@",
  43. NSStringFromClass([representation class])
  44. );
  45. }
  46. };
  47. NSDictionary *FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping) {
  48. FEMMappingApply(mapping, ^(FEMMapping *object) {
  49. NSCParameterAssert(object.entityName != nil);
  50. });
  51. NSMutableDictionary *output = [[NSMutableDictionary alloc] init];
  52. for (NSString *name in FEMMappingCollectUsedEntityNames(mapping)) {
  53. output[name] = [[NSMutableSet alloc] init];
  54. }
  55. id root = FEMRepresentationRootForKeyPath(representation, mapping.rootPath);
  56. _FEMRepresentationCollectPresentedPrimaryKeys(root, mapping, output);
  57. return output;
  58. }
  59. id FEMRepresentationValueForAttribute(id representation, FEMAttribute *attribute) {
  60. id value = attribute.keyPath ? [representation valueForKeyPath:attribute.keyPath] : representation;
  61. // nil is a valid value for missing keys. therefore attribute is discarded
  62. if (value != nil) {
  63. // if by mistake nil returned we still have to map it to the NSNull to indicate missing value
  64. return [attribute mapValue:value] ?: [NSNull null];
  65. }
  66. return value;
  67. }