diff --git a/FastEasyMapping/Source/Cache/FEMObjectCache.h b/FastEasyMapping/Source/Cache/FEMObjectCache.h index b72b685..d7e0868 100644 --- a/FastEasyMapping/Source/Cache/FEMObjectCache.h +++ b/FastEasyMapping/Source/Cache/FEMObjectCache.h @@ -24,7 +24,7 @@ typedef _Nonnull id (^FEMObjectCacheSource)(FEMMapping *mappi @interface FEMObjectCache (CoreData) - (instancetype)initWithContext:(NSManagedObjectContext *)context - presentedPrimaryKeys:(nullable NSMapTable *> *)presentedPrimaryKeys; + presentedPrimaryKeys:(nullable NSDictionary *> *)presentedPrimaryKeys; @end diff --git a/FastEasyMapping/Source/Cache/FEMObjectCache.m b/FastEasyMapping/Source/Cache/FEMObjectCache.m index 0a7a7c2..50c1d59 100644 --- a/FastEasyMapping/Source/Cache/FEMObjectCache.m +++ b/FastEasyMapping/Source/Cache/FEMObjectCache.m @@ -74,10 +74,10 @@ - (NSDictionary *)objectsForMapping:(FEMMapping *)mapping { @implementation FEMObjectCache (CoreData) - (instancetype)initWithContext:(NSManagedObjectContext *)context - presentedPrimaryKeys:(nullable NSMapTable *> *)presentedPrimaryKeys + presentedPrimaryKeys:(nullable NSDictionary *> *)presentedPrimaryKeys { return [self initWithSource:^id (FEMMapping *mapping) { - NSSet *primaryKeys = [presentedPrimaryKeys objectForKey:mapping]; + NSSet *primaryKeys = presentedPrimaryKeys[mapping.uniqueIdentifier]; if (primaryKeys.count > 0) { NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:mapping.entityName]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K IN %@", mapping.primaryKey, primaryKeys]; diff --git a/FastEasyMapping/Source/Deserializer/FEMDeserializer.m b/FastEasyMapping/Source/Deserializer/FEMDeserializer.m index 054330e..c945cdb 100644 --- a/FastEasyMapping/Source/Deserializer/FEMDeserializer.m +++ b/FastEasyMapping/Source/Deserializer/FEMDeserializer.m @@ -172,7 +172,7 @@ - (NSArray *)_collectionFromRepresentation:(NSArray *)representation mapping:(FE } - (void)beginTransactionForMapping:(FEMMapping *)mapping representation:(NSArray *)representation { - NSMapTable *presentedPrimaryKeys = nil; + NSDictionary *> *presentedPrimaryKeys = nil; if ([[self.store class] requiresPrefetch]) { presentedPrimaryKeys = FEMRepresentationCollectPresentedPrimaryKeys(representation, mapping); } diff --git a/FastEasyMapping/Source/Store/FEMManagedObjectStore.m b/FastEasyMapping/Source/Store/FEMManagedObjectStore.m index 8cd215c..320cbaf 100644 --- a/FastEasyMapping/Source/Store/FEMManagedObjectStore.m +++ b/FastEasyMapping/Source/Store/FEMManagedObjectStore.m @@ -30,7 +30,7 @@ - (instancetype)initWithContext:(NSManagedObjectContext *)context { #pragma mark - Transaction -- (void)beginTransaction:(nullable NSMapTable *> *)presentedPrimaryKeys { +- (void)beginTransaction:(nullable NSDictionary *> *)presentedPrimaryKeys { _cache = [[FEMObjectCache alloc] initWithContext:self.context presentedPrimaryKeys:presentedPrimaryKeys]; } diff --git a/FastEasyMapping/Source/Store/FEMObjectStore.h b/FastEasyMapping/Source/Store/FEMObjectStore.h index 9b1b8f4..b0612b2 100644 --- a/FastEasyMapping/Source/Store/FEMObjectStore.h +++ b/FastEasyMapping/Source/Store/FEMObjectStore.h @@ -23,9 +23,9 @@ NS_ASSUME_NONNULL_BEGIN @discussion Invoked by FEMDeserializer at the very beginning of deserialization. Custom implementation may want to begin write transaction or similar. Default implementation does nothing. - @param presentedPrimaryKeys when `+[YourObjectStoreSubclass requiresPrefetch]` returns `YES` then `presentedPrimaryKeys contains a non-nil MapTable with FEMMapping to Set of primary keys pairs. In case +requiresPrefetch returns NO - nil value passed. + @param presentedPrimaryKeys when `+[YourObjectStoreSubclass requiresPrefetch]` returns `YES` then `presentedPrimaryKeys contains a non-nil Dictionary with `-[FEMMapping uniqueIdentifier]` to Set of primary keys pairs. In case +requiresPrefetch returns NO - nil value passed. */ -- (void)beginTransaction:(nullable NSMapTable *> *)presentedPrimaryKeys; +- (void)beginTransaction:(nullable NSDictionary *> *)presentedPrimaryKeys; /** @discussion Invoked by FEMDeserializer after all data has been deserialized. diff --git a/FastEasyMapping/Source/Store/FEMObjectStore.m b/FastEasyMapping/Source/Store/FEMObjectStore.m index 6cd8867..301e0f7 100644 --- a/FastEasyMapping/Source/Store/FEMObjectStore.m +++ b/FastEasyMapping/Source/Store/FEMObjectStore.m @@ -5,7 +5,7 @@ @implementation FEMObjectStore -- (void)beginTransaction:(nullable NSMapTable *> *)presentedPrimaryKeys { +- (void)beginTransaction:(nullable NSDictionary *> *)presentedPrimaryKeys { // no-op } diff --git a/FastEasyMapping/Source/Utility/FEMRepresentationUtility.h b/FastEasyMapping/Source/Utility/FEMRepresentationUtility.h index 827c7bb..d33b704 100644 --- a/FastEasyMapping/Source/Utility/FEMRepresentationUtility.h +++ b/FastEasyMapping/Source/Utility/FEMRepresentationUtility.h @@ -8,7 +8,8 @@ NS_ASSUME_NONNULL_BEGIN FOUNDATION_EXTERN id FEMRepresentationRootForKeyPath(id representation, NSString *keyPath); -FOUNDATION_EXTERN NSMapTable *> *FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping); +/// Returns map of primary keys per mapping. Note that key represented by the `-[FEMMapping uniqueIdentifier]`. +FOUNDATION_EXTERN NSDictionary *> *FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping); FOUNDATION_EXTERN _Nullable id FEMRepresentationValueForAttribute(id representation, FEMAttribute *attribute); diff --git a/FastEasyMapping/Source/Utility/FEMRepresentationUtility.m b/FastEasyMapping/Source/Utility/FEMRepresentationUtility.m index 15cd25f..ef9169b 100644 --- a/FastEasyMapping/Source/Utility/FEMRepresentationUtility.m +++ b/FastEasyMapping/Source/Utility/FEMRepresentationUtility.m @@ -12,13 +12,13 @@ id FEMRepresentationRootForKeyPath(id representation, NSString *keyPath) { return representation; } -void _FEMRepresentationCollectPresentedPrimaryKeys(id, FEMMapping *, NSMapTable *> *); +void _FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping, NSMutableDictionary *> *container); -void _FEMRepresentationCollectObjectPrimaryKeys(id object, FEMMapping *mapping, NSMapTable *> *container) { +void _FEMRepresentationCollectObjectPrimaryKeys(id object, FEMMapping *mapping, NSMutableDictionary *> *container) { if (mapping.primaryKeyAttribute) { id value = FEMRepresentationValueForAttribute(object, mapping.primaryKeyAttribute); if (value && value != NSNull.null) { - [[container objectForKey:mapping] addObject:value]; + [[container objectForKey:mapping.uniqueIdentifier] addObject:value]; } } @@ -30,7 +30,7 @@ void _FEMRepresentationCollectObjectPrimaryKeys(id object, FEMMapping *mapping, } } -void _FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping, NSMapTable *> *container) { +void _FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping, NSMutableDictionary *> *container) { if ([representation isKindOfClass:[NSArray class]]) { for (id object in (id)representation) { _FEMRepresentationCollectObjectPrimaryKeys(object, mapping, container); @@ -48,14 +48,18 @@ void _FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping } }; -NSMapTable *> *FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping) { +NSDictionary *> *FEMRepresentationCollectPresentedPrimaryKeys(id representation, FEMMapping *mapping) { NSSet *flattenMappings = [mapping flatten]; - - NSPointerFunctionsOptions options = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality; - NSMapTable *map = [[NSMapTable alloc] initWithKeyOptions:options valueOptions:options capacity:flattenMappings.count]; + + NSMutableDictionary *> *map = [[NSMutableDictionary alloc] initWithCapacity:flattenMappings.count]; for (FEMMapping *key in flattenMappings) { - [map setObject:[NSMutableSet new] forKey:key]; + // When we have a set of different mappings that describes same entity / objectClass (indirect recursive relationship) + // then store interested in unified map where all of the primary keys from the different mappings but identical entity + // has the same key + if ([map objectForKey:key.uniqueIdentifier] == nil) { + [map setObject:[NSMutableSet new] forKey:key.uniqueIdentifier]; + } } id root = FEMRepresentationRootForKeyPath(representation, mapping.rootPath);