diff --git a/Code/CoreData/RKManagedObjectMappingOperationDataSource.m b/Code/CoreData/RKManagedObjectMappingOperationDataSource.m index cf6b3671..6f1f2d5b 100644 --- a/Code/CoreData/RKManagedObjectMappingOperationDataSource.m +++ b/Code/CoreData/RKManagedObjectMappingOperationDataSource.m @@ -38,9 +38,9 @@ } -- (id)objectForMappableContent:(id)mappableContent mapping:(RKObjectMapping *)mapping +- (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRepresentation:(NSDictionary *)representation withMapping:(RKObjectMapping *)mapping { - NSAssert(mappableContent, @"Mappable data cannot be nil"); + NSAssert(representation, @"Mappable data cannot be nil"); NSAssert(self.managedObjectContext, @"%@ must be initialized with a managed object context.", [self class]); if (! [mapping isKindOfClass:[RKEntityMapping class]]) { @@ -69,11 +69,11 @@ // Get the primary key value out of the mappable data (if any) if ([primaryKeyAttributeMapping isMappingForKeyOfNestedDictionary]) { RKLogDebug(@"Detected use of nested dictionary key as primaryKey attribute..."); - primaryKeyValue = [[mappableContent allKeys] lastObject]; + primaryKeyValue = [[representation allKeys] lastObject]; } else { NSString* keyPathForPrimaryKeyElement = primaryKeyAttributeMapping.sourceKeyPath; if (keyPathForPrimaryKeyElement) { - primaryKeyValue = [mappableContent valueForKeyPath:keyPathForPrimaryKeyElement]; + primaryKeyValue = [representation valueForKeyPath:keyPathForPrimaryKeyElement]; } else { RKLogWarning(@"Unable to find source attribute for primaryKeyAttribute '%@': unable to find existing object instances by primary key.", primaryKeyAttribute); } diff --git a/Code/ObjectMapping/RKMappingOperation.m b/Code/ObjectMapping/RKMappingOperation.m index ec980003..a5d0e97c 100644 --- a/Code/ObjectMapping/RKMappingOperation.m +++ b/Code/ObjectMapping/RKMappingOperation.m @@ -530,7 +530,7 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) { } else { NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([mapping class])); } - id mappableObject = [self.dataSource objectForMappableContent:nestedObject mapping:objectMapping]; + id mappableObject = [self.dataSource mappingOperation:self targetObjectForRepresentation:nestedObject withMapping:objectMapping]; if ([self mapNestedObject:nestedObject toObject:mappableObject withRelationshipMapping:relationshipMapping]) { [destinationObject addObject:mappableObject]; } @@ -583,7 +583,7 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) { objectMapping = (RKObjectMapping *)mapping; } NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([mapping class])); - destinationObject = [self.dataSource objectForMappableContent:value mapping:objectMapping]; + destinationObject = [self.dataSource mappingOperation:self targetObjectForRepresentation:value withMapping:objectMapping]; if ([self mapNestedObject:value toObject:destinationObject withRelationshipMapping:relationshipMapping]) { appliedMappings = YES; } diff --git a/Code/ObjectMapping/RKMappingOperationDataSource.h b/Code/ObjectMapping/RKMappingOperationDataSource.h index f3fcb8f3..0f44bac0 100644 --- a/Code/ObjectMapping/RKMappingOperationDataSource.h +++ b/Code/ObjectMapping/RKMappingOperationDataSource.h @@ -5,18 +5,54 @@ // Created by Blake Watters on 7/3/12. // Copyright (c) 2012 RestKit. All rights reserved. // +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #import @class RKObjectMapping, RKMappingOperation; -// Data source for mapping operations +/** + An object that adopts the `RKMappingOperationDataSource` protocol is responsible for the retrieval or creation of target objects within an `RKObjectMapper` or `RKMappingOperation`. A data source is responsible for meeting the requirements of the underlying data store implementation and must return a key-value coding compliant object instance that can be used as the target object of a mapping operation. It is also responsible for commiting any changes necessary to the underlying data store once a mapping operation has completed its work. + + At a minimum, a data source must implement the `mappingOperation:targetObjectForRepresentation:withMapping:` method. This method is responsible for finding an existing object instance to be updated or creating a new object if no existing object could be found or the underlying data store does not support persistence. Object mapping operations which target `NSObject` derived classes will always result in mapping to new transient objects, while persistent data stores such as Core Data can be queried to retrieve existing objects for update. + + @see `RKManagedObjectMappingOperationDataSource` + */ @protocol RKMappingOperationDataSource @required -- (id)objectForMappableContent:(id)mappableContent mapping:(RKObjectMapping *)mapping; + +/** + Asks the data source for the target object for an object mapping operation given an `NSDictionary` representation of the object's properties and the mapping object that will be used to perform the mapping. + + The `representation` value is a fragment of content from a deserialized response that has been identified as containing content that is mappable using the given mapping. + + @param mappingOperation The mapping operation requesting the target object. + @param representation A dictionary representation of the properties to be mapped onto the retrieved target object. + @param mapping The object mapping to be used to perform a mapping from the representation to the target object. + @return A key-value coding compliant object to perform the mapping on to. + */ +- (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRepresentation:(NSDictionary *)representation withMapping:(RKObjectMapping *)mapping; @optional + +/** + Tells the data source to commit any changes to the underlying data store. + + @param mappingOperation The mapping operation that has completed its work. + */ +// TODO: better name? - (void)commitChangesForMappingOperation:(RKMappingOperation *)mappingOperation; @end diff --git a/Code/ObjectMapping/RKObjectMapper.m b/Code/ObjectMapping/RKObjectMapper.m index de9d1186..f62065da 100644 --- a/Code/ObjectMapping/RKObjectMapper.m +++ b/Code/ObjectMapping/RKObjectMapper.m @@ -252,8 +252,7 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath"; } if (objectMapping) { - id object = [self.mappingOperationDataSource objectForMappableContent:mappableData mapping:objectMapping]; - return object; + return [self.mappingOperationDataSource mappingOperation:nil targetObjectForRepresentation:mappableData withMapping:objectMapping]; } return nil; diff --git a/Code/ObjectMapping/RKObjectMappingOperationDataSource.h b/Code/ObjectMapping/RKObjectMappingOperationDataSource.h index 2c1aa215..3daf2166 100644 --- a/Code/ObjectMapping/RKObjectMappingOperationDataSource.h +++ b/Code/ObjectMapping/RKObjectMappingOperationDataSource.h @@ -5,8 +5,23 @@ // Created by Blake Watters on 7/3/12. // Copyright (c) 2012 RestKit. All rights reserved. // +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #import "RKMappingOperationDataSource.h" +/** + The `RKObjectMappingOperationDataSource` class is an implementation of the `RKMappingOperationDataSource` protocol for use in performing object mappings that target plain old `NSObject` derived classes (as opposed to `NSManagedObject` derived persistent entities). + */ @interface RKObjectMappingOperationDataSource : NSObject @end diff --git a/Code/ObjectMapping/RKObjectMappingOperationDataSource.m b/Code/ObjectMapping/RKObjectMappingOperationDataSource.m index eb450d08..c8b53f61 100644 --- a/Code/ObjectMapping/RKObjectMappingOperationDataSource.m +++ b/Code/ObjectMapping/RKObjectMappingOperationDataSource.m @@ -5,13 +5,25 @@ // Created by Blake Watters on 7/3/12. // Copyright (c) 2012 RestKit. All rights reserved. // +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #import "RKObjectMappingOperationDataSource.h" #import "RKObjectMapping.h" @implementation RKObjectMappingOperationDataSource -- (id)objectForMappableContent:(id)mappableContent mapping:(RKObjectMapping *)mapping +- (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRepresentation:(NSDictionary *)representation withMapping:(RKObjectMapping *)mapping { return [mapping.objectClass new]; } diff --git a/Code/Testing/RKMappingTest.m b/Code/Testing/RKMappingTest.m index 08acdffc..227be7fa 100644 --- a/Code/Testing/RKMappingTest.m +++ b/Code/Testing/RKMappingTest.m @@ -211,7 +211,7 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue); if (! self.hasPerformedMapping) { id sourceObject = self.rootKeyPath ? [self.sourceObject valueForKeyPath:self.rootKeyPath] : self.sourceObject; if (nil == self.destinationObject) { - self.destinationObject = [self.mappingOperationDataSource objectForMappableContent:self.sourceObject mapping:self.mapping]; + self.destinationObject = [self.mappingOperationDataSource mappingOperation:nil targetObjectForRepresentation:self.sourceObject withMapping:self.mapping]; } RKMappingOperation *mappingOperation = [RKMappingOperation mappingOperationFromObject:sourceObject toObject:self.destinationObject withMapping:self.mapping]; mappingOperation.dataSource = self.mappingOperationDataSource;