Renamed Polymorphic mapping to dynamic mapping after consulting with the community. Dropped abstract superclass in favor of a RKObjectMappingDefinition protocol. Caught missing cases with dynamic object mapping + targetObject. Updated docs and method signatures to reflect the updates.

This commit is contained in:
Blake Watters
2011-07-31 19:37:42 -04:00
parent eab35ef3f7
commit 4e03ba7bef
27 changed files with 315 additions and 268 deletions

View File

@@ -1,19 +0,0 @@
//
// RKObjectAbstractMapping.h
// RestKit
//
// Created by Blake Watters on 7/29/11.
// Copyright 2011 RestKit. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
An abstract superclass for RKObjectMapping and RKObjectPolymorphic mapping.
Provides type safety checks
*/
@interface RKObjectAbstractMapping : NSObject
- (BOOL)forceCollectionMapping;
- (Class)objectClass;
@end

View File

@@ -1,25 +0,0 @@
//
// RKObjectAbstractMapping.m
// RestKit
//
// Created by Blake Watters on 7/29/11.
// Copyright 2011 RestKit. All rights reserved.
//
#import "RKObjectAbstractMapping.h"
@implementation RKObjectAbstractMapping
- (BOOL)forceCollectionMapping {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
}
- (Class)objectClass {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
}
@end

View File

@@ -6,13 +6,13 @@
// Copyright 2011 Two Toasters. All rights reserved.
//
#import "RKObjectAbstractMapping.h"
#import "RKObjectMappingDefinition.h"
#import "RKObjectMapping.h"
/**
Return the appropriate object mapping given a mappable data
*/
@protocol RKObjectPolymorphicMappingDelegate <NSObject>
@protocol RKObjectDynamicMappingDelegate <NSObject>
@required
- (RKObjectMapping*)objectMappingForData:(id)data;
@@ -20,19 +20,19 @@
@end
#ifdef NS_BLOCKS_AVAILABLE
typedef RKObjectMapping*(^RKObjectPolymorphicMappingDelegateBlock)(id);
typedef RKObjectMapping*(^RKObjectDynamicMappingDelegateBlock)(id);
#endif
/**
Defines a polymorphic object mapping that determines the appropriate concrete
Defines a dynamic object mapping that determines the appropriate concrete
object mapping to apply at mapping time. This allows you to map very similar payloads
differently depending on the type of data contained therein.
*/
@interface RKObjectPolymorphicMapping : RKObjectAbstractMapping {
@interface RKObjectDynamicMapping : NSObject <RKObjectMappingDefinition> {
NSMutableArray* _matchers;
id<RKObjectPolymorphicMappingDelegate> _delegate;
id<RKObjectDynamicMappingDelegate> _delegate;
#ifdef NS_BLOCKS_AVAILABLE
RKObjectPolymorphicMappingDelegateBlock _delegateBlock;
RKObjectDynamicMappingDelegateBlock _objectMappingForDataBlock;
#endif
BOOL _forceCollectionMapping;
}
@@ -43,14 +43,14 @@ typedef RKObjectMapping*(^RKObjectPolymorphicMappingDelegateBlock)(id);
@see RKDynamicObjectMappingDelegate
*/
@property (nonatomic, assign) id<RKObjectPolymorphicMappingDelegate> delegate;
@property (nonatomic, assign) id<RKObjectDynamicMappingDelegate> delegate;
#ifdef NS_BLOCKS_AVAILABLE
/**
A block to invoke to determine the appropriate concrete object mapping
to apply to the mappable data.
*/
@property (nonatomic, copy) RKObjectPolymorphicMappingDelegateBlock delegateBlock;
@property (nonatomic, copy) RKObjectDynamicMappingDelegateBlock objectMappingForDataBlock;
#endif
/**
@@ -61,35 +61,32 @@ typedef RKObjectMapping*(^RKObjectPolymorphicMappingDelegateBlock)(id);
@property (nonatomic, assign) BOOL forceCollectionMapping;
/**
Return a new auto-released polymorphic object mapping
Return a new auto-released dynamic object mapping
*/
+ (RKObjectPolymorphicMapping*)polymorphicMapping;
+ (RKObjectDynamicMapping*)dynamicMapping;
#if NS_BLOCKS_AVAILABLE
/**
Return a new auto-released polymorphic object mapping after yielding it to the block for configuration
Return a new auto-released dynamic object mapping after yielding it to the block for configuration
*/
+ (RKObjectPolymorphicMapping*)polymorphicMappingWithBlock:(void(^)(RKObjectPolymorphicMapping*))block;
+ (RKObjectDynamicMapping*)dynamicMappingWithBlock:(void(^)(RKObjectDynamicMapping*))block;
#endif
//+ (id)mappingForClass:(Class)objectClass block:(void(^)(RKObjectMapping*))block {
// TODO: polymorphicMappingWithBlock
/**
Defines a polymorphic mapping rule stating that when the value of the key property matches the specified
Defines a dynamic mapping rule stating that when the value of the key property matches the specified
value, the objectMapping should be used.
For example, suppose that we have a JSON fragment for a person that we want to map differently based on
the gender of the person. When the gender is 'male', we want to use the Boy class and when then the gender
is 'female' we want to use the Girl class. We might define our polymorphic mapping like so:
is 'female' we want to use the Girl class. We might define our dynamic mapping like so:
RKObjectPolymorphicMapping* mapping = [RKObjectPolymorphicMapping polymorphicMapping];
RKObjectdynamicMapping* mapping = [RKObjectdynamicMapping dynamicMapping];
[mapping setObjectMapping:boyMapping whenValueOfKeyPath:@"gender" isEqualTo:@"male"];
[mapping setObjectMapping:boyMapping whenValueOfKeyPath:@"gender" isEqualTo:@"female"];
*/
- (void)setObjectMapping:(RKObjectMapping*)objectMapping whenValueOfKeyPath:(NSString*)key isEqualTo:(id)value;
- (void)setObjectMapping:(RKObjectMapping*)objectMapping whenValueOfKeyPath:(NSString*)keyPath isEqualTo:(id)value;
/**
Invoked by the RKObjectMapper and RKObjectMappingOperation to determine the appropriate RKObjectMapping to use

View File

@@ -6,7 +6,7 @@
// Copyright 2011 Two Toasters. All rights reserved.
//
#import "RKObjectPolymorphicMapping.h"
#import "RKObjectDynamicMapping.h"
#import "../Support/RKLog.h"
// Set Logging Component
@@ -16,8 +16,8 @@
// Implemented in RKObjectMappingOperation
BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
@interface RKObjectPolymorphicMappingMatcher : NSObject {
NSString* _key;
@interface RKObjectDynamicMappingMatcher : NSObject {
NSString* _keyPath;
id _value;
RKObjectMapping* _objectMapping;
}
@@ -29,14 +29,14 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
- (NSString*)matchDescription;
@end
@implementation RKObjectPolymorphicMappingMatcher
@implementation RKObjectDynamicMappingMatcher
@synthesize objectMapping = _objectMapping;
- (id)initWithKey:(NSString*)key value:(id)value objectMapping:(RKObjectMapping*)objectMapping {
self = [super init];
if (self) {
_key = [key retain];
_keyPath = [key retain];
_value = [value retain];
_objectMapping = [objectMapping retain];
}
@@ -45,38 +45,38 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
}
- (void)dealloc {
[_key release];
[_keyPath release];
[_value release];
[_objectMapping release];
[super dealloc];
}
- (BOOL)isMatchForData:(id)data {
return RKObjectIsValueEqualToValue([data valueForKeyPath:_key], _value);
return RKObjectIsValueEqualToValue([data valueForKeyPath:_keyPath], _value);
}
- (NSString*)matchDescription {
return [NSString stringWithFormat:@"%@ == %@", _key, _value];
return [NSString stringWithFormat:@"%@ == %@", _keyPath, _value];
}
@end
///////////////////////////////////////////////////////////////////////////////////////////////////
@implementation RKObjectPolymorphicMapping
@implementation RKObjectDynamicMapping
@synthesize delegate = _delegate;
@synthesize delegateBlock = _delegateBlock;
@synthesize objectMappingForDataBlock = _objectMappingForDataBlock;
@synthesize forceCollectionMapping = _forceCollectionMapping;
+ (RKObjectPolymorphicMapping*)polymorphicMapping {
+ (RKObjectDynamicMapping*)dynamicMapping {
return [[self new] autorelease];
}
#if NS_BLOCKS_AVAILABLE
+ (RKObjectPolymorphicMapping*)polymorphicMappingWithBlock:(void(^)(RKObjectPolymorphicMapping*))block {
RKObjectPolymorphicMapping* mapping = [self polymorphicMapping];
+ (RKObjectDynamicMapping*)dynamicMappingWithBlock:(void(^)(RKObjectDynamicMapping*))block {
RKObjectDynamicMapping* mapping = [self dynamicMapping];
block(mapping);
return mapping;
}
@@ -97,9 +97,9 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
[super dealloc];
}
- (void)setObjectMapping:(RKObjectMapping*)objectMapping whenValueOfKeyPath:(NSString*)key isEqualTo:(id)value {
RKLogDebug(@"Adding dynamic object mapping for key '%@' with value '%@' to destination class: %@", key, value, NSStringFromClass(objectMapping.objectClass));
RKObjectPolymorphicMappingMatcher* matcher = [[RKObjectPolymorphicMappingMatcher alloc] initWithKey:key value:value objectMapping:objectMapping];
- (void)setObjectMapping:(RKObjectMapping*)objectMapping whenValueOfKeyPath:(NSString*)keyPath isEqualTo:(id)value {
RKLogDebug(@"Adding dynamic object mapping for key '%@' with value '%@' to destination class: %@", keyPath, value, NSStringFromClass(objectMapping.objectClass));
RKObjectDynamicMappingMatcher* matcher = [[RKObjectDynamicMappingMatcher alloc] initWithKey:keyPath value:value objectMapping:objectMapping];
[_matchers addObject:matcher];
[matcher release];
}
@@ -111,7 +111,7 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
RKLogTrace(@"Performing dynamic object mapping for mappable data: %@", data);
// Consult the declarative matchers first
for (RKObjectPolymorphicMappingMatcher* matcher in _matchers) {
for (RKObjectDynamicMappingMatcher* matcher in _matchers) {
if ([matcher isMatchForData:data]) {
RKLogTrace(@"Found declarative match for data: %@.", [matcher matchDescription]);
return matcher.objectMapping;
@@ -127,10 +127,10 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
}
}
if (self.delegateBlock) {
mapping = self.delegateBlock(data);
if (self.objectMappingForDataBlock) {
mapping = self.objectMappingForDataBlock(data);
if (mapping) {
RKLogTrace(@"Found dynamic delegateBlock match. DelegateBlock = %@", self.delegateBlock);
RKLogTrace(@"Found dynamic delegateBlock match. objectMappingForDataBlock = %@", self.objectMappingForDataBlock);
}
}

View File

@@ -26,12 +26,12 @@
- (void)objectMapperWillBeginMapping:(RKObjectMapper*)objectMapper;
- (void)objectMapperDidFinishMapping:(RKObjectMapper*)objectMapper;
- (void)objectMapper:(RKObjectMapper*)objectMapper didAddError:(NSError*)error;
- (void)objectMapper:(RKObjectMapper*)objectMapper didFindMappableObject:(id)object atKeyPath:(NSString*)keyPath withMapping:(RKObjectAbstractMapping*)mapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper didFindMappableObject:(id)object atKeyPath:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)mapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper didNotFindMappableObjectAtKeyPath:(NSString*)keyPath;
- (void)objectMapper:(RKObjectMapper*)objectMapper willMapFromObject:(id)sourceObject toObject:(id)destinationObject atKeyPath:(NSString*)keyPath usingMapping:(RKObjectAbstractMapping*)objectMapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper didMapFromObject:(id)sourceObject toObject:(id)destinationObject atKeyPath:(NSString*)keyPath usingMapping:(RKObjectAbstractMapping*)objectMapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper didFailMappingFromObject:(id)sourceObject toObject:(id)destinationObject withError:(NSError*)error atKeyPath:(NSString*)keyPath usingMapping:(RKObjectAbstractMapping*)objectMapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper willMapFromObject:(id)sourceObject toObject:(id)destinationObject atKeyPath:(NSString*)keyPath usingMapping:(id<RKObjectMappingDefinition>)objectMapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper didMapFromObject:(id)sourceObject toObject:(id)destinationObject atKeyPath:(NSString*)keyPath usingMapping:(id<RKObjectMappingDefinition>)objectMapping;
- (void)objectMapper:(RKObjectMapper*)objectMapper didFailMappingFromObject:(id)sourceObject toObject:(id)destinationObject withError:(NSError*)error atKeyPath:(NSString*)keyPath usingMapping:(id<RKObjectMappingDefinition>)objectMapping;
@end
@interface RKObjectMapper : NSObject {

View File

@@ -97,14 +97,21 @@
#pragma mark - Mapping Primitives
- (id)mapObject:(id)mappableObject atKeyPath:(NSString*)keyPath usingMapping:(RKObjectAbstractMapping*)objectMapping {
- (id)mapObject:(id)mappableObject atKeyPath:(NSString*)keyPath usingMapping:(id<RKObjectMappingDefinition>)mapping {
NSAssert([mappableObject respondsToSelector:@selector(setValue:forKeyPath:)], @"Expected self.object to be KVC compliant");
id destinationObject = nil;
if (self.targetObject) {
// If we find a mapping for this type and keyPath, map the entire dictionary to the target object
destinationObject = self.targetObject;
if (objectMapping && NO == [[self.targetObject class] isSubclassOfClass:objectMapping.objectClass]) {
RKObjectMapping* objectMapping = nil;
if ([mapping isKindOfClass:[RKObjectDynamicMapping class]]) {
objectMapping = [(RKObjectDynamicMapping*)mapping objectMappingForDictionary:mappableObject];
} else if ([mapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)mapping;
} else {
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([mapping class]));
}
if (NO == [[self.targetObject class] isSubclassOfClass:objectMapping.objectClass]) {
NSString* errorMessage = [NSString stringWithFormat:
@"Expected an object mapping for class of type '%@', provider returned one for '%@'",
NSStringFromClass([self.targetObject class]), NSStringFromClass(objectMapping.objectClass)];
@@ -112,11 +119,11 @@
return nil;
}
} else {
destinationObject = [self objectWithMapping:objectMapping andData:mappableObject];
destinationObject = [self objectWithMapping:mapping andData:mappableObject];
}
if (objectMapping && destinationObject) {
BOOL success = [self mapFromObject:mappableObject toObject:destinationObject atKeyPath:keyPath usingMapping:objectMapping];
if (mapping && destinationObject) {
BOOL success = [self mapFromObject:mappableObject toObject:destinationObject atKeyPath:keyPath usingMapping:mapping];
if (success) {
return destinationObject;
}
@@ -129,7 +136,7 @@
return nil;
}
- (NSArray*)mapCollection:(NSArray*)mappableObjects atKeyPath:(NSString*)keyPath usingMapping:(RKObjectAbstractMapping*)mapping {
- (NSArray*)mapCollection:(NSArray*)mappableObjects atKeyPath:(NSString*)keyPath usingMapping:(id<RKObjectMappingDefinition>)mapping {
NSAssert(mappableObjects != nil, @"Cannot map without an collection of mappable objects");
NSAssert(mapping != nil, @"Cannot map without a mapping to consult");
@@ -174,7 +181,7 @@
}
// The workhorse of this entire process. Emits object loading operations
- (BOOL)mapFromObject:(id)mappableObject toObject:(id)destinationObject atKeyPath:keyPath usingMapping:(RKObjectAbstractMapping*)mapping {
- (BOOL)mapFromObject:(id)mappableObject toObject:(id)destinationObject atKeyPath:keyPath usingMapping:(id<RKObjectMappingDefinition>)mapping {
NSAssert(destinationObject != nil, @"Cannot map without a target object to assign the results to");
NSAssert(mappableObject != nil, @"Cannot map without a collection of attributes");
NSAssert(mapping != nil, @"Cannot map without an mapping");
@@ -204,6 +211,27 @@
return success;
}
- (id)objectWithMapping:(id<RKObjectMappingDefinition>)mapping andData:(id)mappableData {
NSAssert([mapping conformsToProtocol:@protocol(RKObjectMappingDefinition)], @"Expected an object implementing RKObjectMappingDefinition");
RKObjectMapping* objectMapping = nil;
if ([mapping isKindOfClass:[RKObjectDynamicMapping class]]) {
objectMapping = [(RKObjectDynamicMapping*)mapping objectMappingForDictionary:mappableData];
if (! objectMapping) {
RKLogDebug(@"Mapping %@ declined mapping for data %@: returned nil objectMapping", mapping, mappableData);
}
} else if ([mapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)mapping;
} else {
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([mapping class]));
}
if (objectMapping) {
return [objectMapping mappableObjectForData:mappableData];
}
return nil;
}
// Primary entry point for the mapper.
- (RKObjectMappingResult*)performMapping {
NSAssert(self.sourceObject != nil, @"Cannot perform object mapping without a source object to map from");
@@ -218,8 +246,8 @@
// Perform the mapping
BOOL foundMappable = NO;
NSMutableDictionary* results = [NSMutableDictionary dictionary];
NSDictionary* keyPathsAndObjectMappings = [self.mappingProvider mappingsByKeyPath];
for (NSString* keyPath in keyPathsAndObjectMappings) {
NSDictionary* mappingsByKeyPath = [self.mappingProvider mappingsByKeyPath];
for (NSString* keyPath in mappingsByKeyPath) {
id mappingResult;
id mappableValue;
@@ -244,7 +272,7 @@
// Found something to map
foundMappable = YES;
RKObjectAbstractMapping* mapping = [keyPathsAndObjectMappings objectForKey:keyPath];
id<RKObjectMappingDefinition> mapping = [mappingsByKeyPath objectForKey:keyPath];
if ([self.delegate respondsToSelector:@selector(objectMapper:didFindMappableObject:atKeyPath:withMapping:)]) {
[self.delegate objectMapper:self didFindMappableObject:mappableValue atKeyPath:keyPath withMapping:mapping];
}
@@ -278,25 +306,4 @@
return [RKObjectMappingResult mappingResultWithDictionary:results];
}
- (id)objectWithMapping:(RKObjectAbstractMapping*)abstractMapping andData:(id)mappableData {
NSAssert(! [abstractMapping isMemberOfClass:[RKObjectAbstractMapping class]], @"Expected a concrete subclass of RKObjectAbstractMapping");
RKObjectMapping* objectMapping = nil;
if ([abstractMapping isKindOfClass:[RKObjectPolymorphicMapping class]]) {
objectMapping = [(RKObjectPolymorphicMapping*)abstractMapping objectMappingForDictionary:mappableData];
if (! objectMapping) {
RKLogDebug(@"Mapping %@ declined mapping for data %@: returned nil objectMapping", abstractMapping, mappableData);
}
} else if ([abstractMapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)abstractMapping;
} else {
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([abstractMapping class]));
}
if (objectMapping) {
return [objectMapping mappableObjectForData:mappableData];
}
return nil;
}
@end

View File

@@ -8,9 +8,9 @@
@interface RKObjectMapper (Private)
- (id)mapObject:(id)mappableObject atKeyPath:keyPath usingMapping:(RKObjectAbstractMapping*)mapping;
- (NSArray*)mapCollection:(NSArray*)mappableObjects atKeyPath:(NSString*)keyPath usingMapping:(RKObjectAbstractMapping*)mapping;
- (BOOL)mapFromObject:(id)mappableObject toObject:(id)destinationObject atKeyPath:keyPath usingMapping:(RKObjectAbstractMapping*)mapping;
- (id)objectWithMapping:(RKObjectAbstractMapping*)objectMapping andData:(id)mappableData;
- (id)mapObject:(id)mappableObject atKeyPath:keyPath usingMapping:(id<RKObjectMappingDefinition>)mapping;
- (NSArray*)mapCollection:(NSArray*)mappableObjects atKeyPath:(NSString*)keyPath usingMapping:(id<RKObjectMappingDefinition>)mapping;
- (BOOL)mapFromObject:(id)mappableObject toObject:(id)destinationObject atKeyPath:keyPath usingMapping:(id<RKObjectMappingDefinition>)mapping;
- (id)objectWithMapping:(id<RKObjectMappingDefinition>)objectMapping andData:(id)mappableData;
@end

View File

@@ -7,7 +7,7 @@
//
#import <Foundation/Foundation.h>
#import "RKObjectAbstractMapping.h"
#import "RKObjectMappingDefinition.h"
#import "RKObjectAttributeMapping.h"
#import "RKObjectRelationshipMapping.h"
@@ -31,7 +31,7 @@ relationship. Relationships are processed using an object mapping as well.
Instances of RKObjectMapping are used to configure RKObjectMappingOperation instances, which actually
perform the mapping work. Both object loading and serialization are defined in terms of object mappings.
*/
@interface RKObjectMapping : RKObjectAbstractMapping {
@interface RKObjectMapping : NSObject <RKObjectMappingDefinition> {
Class _objectClass;
NSMutableArray* _mappings;
NSMutableArray* _dateFormatStrings;
@@ -248,9 +248,9 @@ relationship. Relationships are processed using an object mapping as well.
@param relationshipKey A key-value coding key corresponding to a value in the mappable source object and a property
on the destination class that have the same name.
@param objectOrPolymorphicMapping An RKObjectMapping or RKObjectPolymorphic mapping to apply when mapping the relationship
@param objectOrDynamicMapping An RKObjectMapping or RKObjectDynamic mapping to apply when mapping the relationship
*/
- (void)mapRelationship:(NSString*)relationshipKey withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping;
- (void)mapRelationship:(NSString*)relationshipKey withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping;
/**
Syntactic sugar to improve readability when defining a relationship mapping. Implies that the mapping
@@ -258,7 +258,7 @@ relationship. Relationships are processed using an object mapping as well.
@see mapRelationship:withObjectMapping:
*/
- (void)hasMany:(NSString*)keyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping;
- (void)hasMany:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping;
/**
Syntactic sugar to improve readability when defining a relationship mapping. Implies that the mapping
@@ -266,7 +266,7 @@ relationship. Relationships are processed using an object mapping as well.
@see mapRelationship:withObjectMapping:
*/
- (void)hasOne:(NSString*)keyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping;
- (void)hasOne:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping;
/**
Instantiate and add an RKObjectAttributeMapping instance targeting a keyPath within the mappable
@@ -307,7 +307,7 @@ relationship. Relationships are processed using an object mapping as well.
@param objectMapping An object mapping to use when processing the nested objects
@see RKObjectRelationshipMapping
*/
- (void)mapKeyPath:(NSString *)sourceKeyPath toRelationship:(NSString*)destinationRelationship withMapping:(RKObjectAbstractMapping *)objectOrPolymorphicMapping;
- (void)mapKeyPath:(NSString *)sourceKeyPath toRelationship:(NSString*)destinationRelationship withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping;
/**
Instantiate and add an RKObjectRelationshipMapping instance targeting a keyPath within the mappable
@@ -322,7 +322,7 @@ relationship. Relationships are processed using an object mapping as well.
@see mapKeyPath:toRelationship:withObjectMapping:
*/
- (void)mapKeyPath:(NSString *)relationshipKeyPath toRelationship:(NSString*)keyPath withMapping:(RKObjectAbstractMapping *)objectOrPolymorphicMapping serialize:(BOOL)serialize;
- (void)mapKeyPath:(NSString *)relationshipKeyPath toRelationship:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping serialize:(BOOL)serialize;
/**
Quickly define a group of attribute mappings using alternating keyPath and attribute names. You must provide

View File

@@ -140,17 +140,17 @@ NSString* const RKObjectMappingNestingAttributeKeyName = @"<RK_NESTING_ATTRIBUTE
[self mapAttributesSet:attributeKeyPaths];
}
- (void)mapKeyPath:(NSString *)relationshipKeyPath toRelationship:(NSString*)keyPath withMapping:(RKObjectAbstractMapping *)objectOrPolymorphicMapping serialize:(BOOL)serialize {
RKObjectRelationshipMapping* mapping = [RKObjectRelationshipMapping mappingFromKeyPath:relationshipKeyPath toKeyPath:keyPath withMapping:objectOrPolymorphicMapping reversible:serialize];
- (void)mapKeyPath:(NSString *)relationshipKeyPath toRelationship:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping serialize:(BOOL)serialize {
RKObjectRelationshipMapping* mapping = [RKObjectRelationshipMapping mappingFromKeyPath:relationshipKeyPath toKeyPath:keyPath withMapping:objectOrDynamicMapping reversible:serialize];
[self addRelationshipMapping:mapping];
}
- (void)mapKeyPath:(NSString *)relationshipKeyPath toRelationship:(NSString*)keyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping {
[self mapKeyPath:relationshipKeyPath toRelationship:keyPath withMapping:objectOrPolymorphicMapping serialize:YES];
- (void)mapKeyPath:(NSString *)relationshipKeyPath toRelationship:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping {
[self mapKeyPath:relationshipKeyPath toRelationship:keyPath withMapping:objectOrDynamicMapping serialize:YES];
}
- (void)mapRelationship:(NSString*)relationshipKeyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping {
[self mapKeyPath:relationshipKeyPath toRelationship:relationshipKeyPath withMapping:objectOrPolymorphicMapping];
- (void)mapRelationship:(NSString*)relationshipKeyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping {
[self mapKeyPath:relationshipKeyPath toRelationship:relationshipKeyPath withMapping:objectOrDynamicMapping];
}
- (void)mapKeyPath:(NSString*)sourceKeyPath toAttribute:(NSString*)destinationKeyPath {
@@ -158,12 +158,12 @@ NSString* const RKObjectMappingNestingAttributeKeyName = @"<RK_NESTING_ATTRIBUTE
[self addAttributeMapping:mapping];
}
- (void)hasMany:(NSString*)keyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping {
[self mapRelationship:keyPath withMapping:objectOrPolymorphicMapping];
- (void)hasMany:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping {
[self mapRelationship:keyPath withMapping:objectOrDynamicMapping];
}
- (void)hasOne:(NSString*)keyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping {
[self mapRelationship:keyPath withMapping:objectOrPolymorphicMapping];
- (void)hasOne:(NSString*)keyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping {
[self mapRelationship:keyPath withMapping:objectOrDynamicMapping];
}
- (void)removeAllMappings {
@@ -191,7 +191,7 @@ NSString* const RKObjectMappingNestingAttributeKeyName = @"<RK_NESTING_ATTRIBUTE
for (RKObjectRelationshipMapping* relationshipMapping in self.relationshipMappings) {
if (relationshipMapping.reversible) {
RKObjectAbstractMapping* mapping = relationshipMapping.mapping;
id<RKObjectMappingDefinition> mapping = relationshipMapping.mapping;
if (! [mapping isKindOfClass:[RKObjectMapping class]]) {
RKLogWarning(@"Unable to generate inverse mapping for relationship '%@': %@ relationships cannot be inversed.", relationshipMapping.sourceKeyPath, NSStringFromClass([mapping class]));
continue;

View File

@@ -0,0 +1,13 @@
//
// RKObjectMappingDefinition.h
// RestKit
//
// Created by Blake Watters on 7/31/11.
// Copyright 2011 RestKit. All rights reserved.
//
@protocol RKObjectMappingDefinition <NSObject>
- (BOOL)forceCollectionMapping;
@end

View File

@@ -59,12 +59,12 @@
Create a new mapping operation configured to transform the object representation
in a source object to a new destination object according to an object mapping definition
*/
+ (RKObjectMappingOperation*)mappingOperationFromObject:(id)sourceObject toObject:(id)destinationObject withMapping:(RKObjectAbstractMapping*)mapping;
+ (RKObjectMappingOperation*)mappingOperationFromObject:(id)sourceObject toObject:(id)destinationObject withMapping:(id<RKObjectMappingDefinition>)mapping;
/**
Initialize a mapping operation for an object and set of data at a particular key path with an object mapping definition
*/
- (id)initWithSourceObject:(id)sourceObject destinationObject:(id)destinationObject mapping:(RKObjectAbstractMapping*)mapping;
- (id)initWithSourceObject:(id)sourceObject destinationObject:(id)destinationObject mapping:(id<RKObjectMappingDefinition>)mapping;
/**
Process all mappable values from the mappable dictionary and assign them to the target object

View File

@@ -58,11 +58,11 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
@synthesize objectMapping = _objectMapping;
@synthesize delegate = _delegate;
+ (RKObjectMappingOperation*)mappingOperationFromObject:(id)sourceObject toObject:(id)destinationObject withMapping:(RKObjectAbstractMapping*)objectMapping {
+ (RKObjectMappingOperation*)mappingOperationFromObject:(id)sourceObject toObject:(id)destinationObject withMapping:(id<RKObjectMappingDefinition>)objectMapping {
return [[[self alloc] initWithSourceObject:sourceObject destinationObject:destinationObject mapping:objectMapping] autorelease];
}
- (id)initWithSourceObject:(id)sourceObject destinationObject:(id)destinationObject mapping:(RKObjectAbstractMapping*)objectMapping {
- (id)initWithSourceObject:(id)sourceObject destinationObject:(id)destinationObject mapping:(id<RKObjectMappingDefinition>)objectMapping {
NSAssert(sourceObject != nil, @"Cannot perform a mapping operation without a sourceObject object");
NSAssert(destinationObject != nil, @"Cannot perform a mapping operation without a destinationObject");
NSAssert(objectMapping != nil, @"Cannot perform a mapping operation without a mapping");
@@ -72,9 +72,9 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
_sourceObject = [sourceObject retain];
_destinationObject = [destinationObject retain];
if ([objectMapping isKindOfClass:[RKObjectPolymorphicMapping class]]) {
_objectMapping = [[(RKObjectPolymorphicMapping*)objectMapping objectMappingForDictionary:_sourceObject] retain];
RKLogDebug(@"RKObjectMappingOperation was initialized with a polymorphic mapping. Determined concrete mapping = %@", _objectMapping);
if ([objectMapping isKindOfClass:[RKObjectDynamicMapping class]]) {
_objectMapping = [[(RKObjectDynamicMapping*)objectMapping objectMappingForDictionary:_sourceObject] retain];
RKLogDebug(@"RKObjectMappingOperation was initialized with a dynamic mapping. Determined concrete mapping = %@", _objectMapping);
} else if ([objectMapping isKindOfClass:[RKObjectMapping class]]) {
_objectMapping = (RKObjectMapping*)[objectMapping retain];
}
@@ -352,18 +352,18 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
destinationObject = [NSMutableArray arrayWithCapacity:[value count]];
for (id nestedObject in value) {
RKObjectAbstractMapping* abstractMapping = relationshipMapping.mapping;
id<RKObjectMappingDefinition> mapping = relationshipMapping.mapping;
RKObjectMapping* objectMapping = nil;
if ([abstractMapping isKindOfClass:[RKObjectPolymorphicMapping class]]) {
objectMapping = [(RKObjectPolymorphicMapping*)abstractMapping objectMappingForDictionary:nestedObject];
if ([mapping isKindOfClass:[RKObjectDynamicMapping class]]) {
objectMapping = [(RKObjectDynamicMapping*)mapping objectMappingForDictionary:nestedObject];
if (! objectMapping) {
RKLogDebug(@"Mapping %@ declined mapping for data %@: returned nil objectMapping", abstractMapping, nestedObject);
RKLogDebug(@"Mapping %@ declined mapping for data %@: returned nil objectMapping", mapping, nestedObject);
continue;
}
} else if ([abstractMapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)abstractMapping;
} else if ([mapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)mapping;
} else {
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([abstractMapping class]));
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([mapping class]));
}
id mappedObject = [objectMapping mappableObjectForData:nestedObject];
if ([self mapNestedObject:nestedObject toObject:mappedObject withRealtionshipMapping:relationshipMapping]) {
@@ -380,14 +380,14 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
// One to one relationship
RKLogDebug(@"Mapping one to one relationship value at keyPath '%@' to '%@'", relationshipMapping.sourceKeyPath, relationshipMapping.destinationKeyPath);
RKObjectAbstractMapping* abstractMapping = relationshipMapping.mapping;
id<RKObjectMappingDefinition> mapping = relationshipMapping.mapping;
RKObjectMapping* objectMapping = nil;
if ([abstractMapping isKindOfClass:[RKObjectPolymorphicMapping class]]) {
objectMapping = [(RKObjectPolymorphicMapping*)abstractMapping objectMappingForDictionary:value];
} else if ([abstractMapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)abstractMapping;
if ([mapping isKindOfClass:[RKObjectDynamicMapping class]]) {
objectMapping = [(RKObjectDynamicMapping*)mapping objectMappingForDictionary:value];
} else if ([mapping isKindOfClass:[RKObjectMapping class]]) {
objectMapping = (RKObjectMapping*)mapping;
}
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([abstractMapping class]));
NSAssert(objectMapping, @"Encountered unknown mapping type '%@'", NSStringFromClass([mapping class]));
destinationObject = [objectMapping mappableObjectForData:value];
if ([self mapNestedObject:value toObject:destinationObject withRealtionshipMapping:relationshipMapping]) {
appliedMappings = YES;

View File

@@ -7,7 +7,7 @@
//
#import "RKObjectMapping.h"
#import "RKObjectPolymorphicMapping.h"
#import "RKObjectDynamicMapping.h"
/**
Responsible for providing object mappings to an instance of the object mapper
@@ -19,21 +19,26 @@
NSMutableDictionary* _serializationMappings;
}
/**
Returns a new auto-released mapping provider
*/
+ (RKObjectMappingProvider*)mappingProvider;
/**
Instructs the mapping provider to use the mapping provided when it encounters content at the specified
key path
*/
- (void)setMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping forKeyPath:(NSString*)keyPath;
- (void)setMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping forKeyPath:(NSString*)keyPath;
/**
Returns the RKObjectMapping or RKObjectPolymorphic mapping configured for use
Returns the RKObjectMapping or RKObjectDynamic mapping configured for use
when mappable content is encountered at keyPath
*/
- (RKObjectAbstractMapping*)mappingForKeyPath:(NSString*)keyPath;
- (id<RKObjectMappingDefinition>)mappingForKeyPath:(NSString*)keyPath;
/**
Returns a dictionary where the keys are mappable keyPaths and the values are the RKObjectMapping
or RKObjectPolymorphic mappings to use for mappable data that appears at the keyPath.
or RKObjectDynamic mappings to use for mappable data that appears at the keyPath.
*/
- (NSDictionary*)mappingsByKeyPath;

View File

@@ -10,6 +10,10 @@
@implementation RKObjectMappingProvider
+ (RKObjectMappingProvider*)mappingProvider {
return [[self new] autorelease];
}
- (id)init {
if ((self = [super init])) {
_objectMappings = [NSMutableArray new];
@@ -30,7 +34,7 @@
[_mappingsByKeyPath setValue:mapping forKey:keyPath];
}
- (RKObjectAbstractMapping*)mappingForKeyPath:(NSString*)keyPath {
- (id<RKObjectMappingDefinition>)mappingForKeyPath:(NSString*)keyPath {
return [_mappingsByKeyPath objectForKey:keyPath];
}

View File

@@ -8,19 +8,20 @@
#import <Foundation/Foundation.h>
#import "RKObjectAttributeMapping.h"
#import "RKObjectMappingDefinition.h"
@class RKObjectAbstractMapping;
@class RKObjectmapping;
@interface RKObjectRelationshipMapping : RKObjectAttributeMapping {
RKObjectAbstractMapping* _mapping;
id<RKObjectMappingDefinition> _mapping;
BOOL _reversible;
}
@property (nonatomic, retain) RKObjectAbstractMapping* mapping;
@property (nonatomic, retain) id<RKObjectMappingDefinition> mapping;
@property (nonatomic, assign) BOOL reversible;
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping;
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping;
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping reversible:(BOOL)reversible;
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping reversible:(BOOL)reversible;
@end

View File

@@ -13,15 +13,15 @@
@synthesize mapping = _mapping;
@synthesize reversible = _reversible;
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping reversible:(BOOL)reversible {
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping reversible:(BOOL)reversible {
RKObjectRelationshipMapping* relationshipMapping = (RKObjectRelationshipMapping*) [self mappingFromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath];
relationshipMapping.reversible = reversible;
relationshipMapping.mapping = objectOrPolymorphicMapping;
relationshipMapping.mapping = objectOrDynamicMapping;
return relationshipMapping;
}
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(RKObjectAbstractMapping*)objectOrPolymorphicMapping {
return [self mappingFromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrPolymorphicMapping reversible:YES];
+ (RKObjectRelationshipMapping*)mappingFromKeyPath:(NSString*)sourceKeyPath toKeyPath:(NSString*)destinationKeyPath withMapping:(id<RKObjectMappingDefinition>)objectOrDynamicMapping {
return [self mappingFromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping reversible:YES];
}
- (id)copyWithZone:(NSZone *)zone {