mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-23 04:20:21 +08:00
* Inversing non intelligently walks the mapping graph, ensuring that cyclic graphs are resolved properly * Copy all attributes from the parent to the inverse mapping (date formatters, etc)
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
#import "RKObjectMapping.h"
|
||||
#import "RKRelationshipMapping.h"
|
||||
#import "RKPropertyInspector.h"
|
||||
@@ -30,13 +31,71 @@ typedef NSString * (^RKSourceToDesinationKeyTransformationBlock)(RKObjectMapping
|
||||
|
||||
// Constants
|
||||
NSString * const RKObjectMappingNestingAttributeKeyName = @"<RK_NESTING_ATTRIBUTE>";
|
||||
static NSUInteger RKObjectMappingMaximumInverseMappingRecursionDepth = 100;
|
||||
|
||||
// Private declaration
|
||||
NSDate *RKDateFromStringWithFormatters(NSString *dateString, NSArray *formatters);
|
||||
|
||||
static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyTransformationBlock = nil;
|
||||
|
||||
@interface RKObjectMapping (Copying)
|
||||
- (void)copyPropertiesFromMapping:(RKObjectMapping *)mapping;
|
||||
@end
|
||||
|
||||
@interface RKMappingInverter : NSObject
|
||||
@property (nonatomic, strong) RKObjectMapping *mapping;
|
||||
@property (nonatomic, strong) NSMutableDictionary *invertedMappings;
|
||||
|
||||
- (id)initWithMapping:(RKObjectMapping *)mapping;
|
||||
- (RKObjectMapping *)inverseMapping;
|
||||
@end
|
||||
|
||||
@implementation RKMappingInverter
|
||||
|
||||
- (id)initWithMapping:(RKObjectMapping *)mapping
|
||||
{
|
||||
self = [self init];
|
||||
if (self) {
|
||||
self.mapping = mapping;
|
||||
self.invertedMappings = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (RKObjectMapping *)invertMapping:(RKObjectMapping *)mapping
|
||||
{
|
||||
// Use an NSValue to obtain a non-copied key into our inversed mappings dictionary
|
||||
NSValue *dictionaryKey = [NSValue valueWithNonretainedObject:mapping];
|
||||
RKObjectMapping *inverseMapping = [self.invertedMappings objectForKey:dictionaryKey];
|
||||
if (inverseMapping) return inverseMapping;
|
||||
|
||||
inverseMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[self.invertedMappings setObject:inverseMapping forKey:dictionaryKey];
|
||||
[inverseMapping copyPropertiesFromMapping:mapping];
|
||||
|
||||
for (RKAttributeMapping *attributeMapping in mapping.attributeMappings) {
|
||||
[inverseMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:attributeMapping.destinationKeyPath toKeyPath:attributeMapping.sourceKeyPath]];
|
||||
}
|
||||
|
||||
for (RKRelationshipMapping *relationshipMapping in mapping.relationshipMappings) {
|
||||
RKObjectMapping *mapping = (RKObjectMapping *) 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;
|
||||
}
|
||||
RKMapping *inverseRelationshipMapping = [self invertMapping:mapping];
|
||||
if (inverseRelationshipMapping) [inverseMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:relationshipMapping.destinationKeyPath toKeyPath:relationshipMapping.sourceKeyPath withMapping:inverseRelationshipMapping]];
|
||||
}
|
||||
|
||||
return inverseMapping;
|
||||
}
|
||||
|
||||
- (RKObjectMapping *)inverseMapping
|
||||
{
|
||||
return [self invertMapping:self.mapping];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RKPropertyMapping ()
|
||||
@property (nonatomic, weak, readwrite) RKObjectMapping *objectMapping;
|
||||
@end
|
||||
@@ -77,21 +136,26 @@ static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyT
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)copyPropertiesFromMapping:(RKObjectMapping *)mapping
|
||||
{
|
||||
self.setDefaultValueForMissingAttributes = mapping.setDefaultValueForMissingAttributes;
|
||||
self.setNilForMissingRelationships = mapping.setNilForMissingRelationships;
|
||||
self.forceCollectionMapping = mapping.forceCollectionMapping;
|
||||
self.performKeyValueValidation = mapping.performKeyValueValidation;
|
||||
self.dateFormatters = mapping.dateFormatters;
|
||||
self.preferredDateFormatter = mapping.preferredDateFormatter;
|
||||
self.sourceToDestinationKeyTransformationBlock = self.sourceToDestinationKeyTransformationBlock;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
RKObjectMapping *copy = [[[self class] allocWithZone:zone] init];
|
||||
copy.objectClass = self.objectClass;
|
||||
copy.setDefaultValueForMissingAttributes = self.setDefaultValueForMissingAttributes;
|
||||
copy.setNilForMissingRelationships = self.setNilForMissingRelationships;
|
||||
copy.forceCollectionMapping = self.forceCollectionMapping;
|
||||
copy.performKeyValueValidation = self.performKeyValueValidation;
|
||||
copy.dateFormatters = self.dateFormatters;
|
||||
copy.preferredDateFormatter = self.preferredDateFormatter;
|
||||
[copy copyPropertiesFromMapping:self];
|
||||
copy.mutablePropertyMappings = [NSMutableArray new];
|
||||
copy.sourceToDestinationKeyTransformationBlock = self.sourceToDestinationKeyTransformationBlock;
|
||||
|
||||
for (RKPropertyMapping *propertyMapping in self.propertyMappings) {
|
||||
[copy addPropertyMapping:propertyMapping];
|
||||
[copy addPropertyMapping:[propertyMapping copy]];
|
||||
}
|
||||
|
||||
return copy;
|
||||
@@ -264,29 +328,10 @@ static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyT
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)inverseMappingAtDepth:(NSInteger)depth
|
||||
{
|
||||
NSAssert(depth < RKObjectMappingMaximumInverseMappingRecursionDepth, @"Exceeded max recursion level in inverseMapping. This is likely due to a loop in the serialization graph. To break this loop, specify one-way relationships by setting serialize to NO in mapKeyPath:toRelationship:withObjectMapping:serialize:");
|
||||
RKObjectMapping *inverseMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
for (RKAttributeMapping *attributeMapping in self.attributeMappings) {
|
||||
[inverseMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:attributeMapping.destinationKeyPath toKeyPath:attributeMapping.sourceKeyPath]];
|
||||
}
|
||||
|
||||
for (RKRelationshipMapping *relationshipMapping in self.relationshipMappings) {
|
||||
RKMapping *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;
|
||||
}
|
||||
[inverseMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:relationshipMapping.destinationKeyPath toKeyPath:relationshipMapping.sourceKeyPath withMapping:[(RKObjectMapping *)mapping inverseMappingAtDepth:depth+1]]];
|
||||
}
|
||||
|
||||
return inverseMapping;
|
||||
}
|
||||
|
||||
- (instancetype)inverseMapping
|
||||
{
|
||||
return [self inverseMappingAtDepth:0];
|
||||
RKMappingInverter *mappingInverter = [[RKMappingInverter alloc] initWithMapping:self];
|
||||
return [mappingInverter inverseMapping];
|
||||
}
|
||||
|
||||
- (void)addAttributeMappingFromKeyOfRepresentationToAttribute:(NSString *)attributeName
|
||||
|
||||
Reference in New Issue
Block a user