mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-28 12:45:33 +08:00
Initial integration of new RKMappingDescriptor class. Convert RKObjectMapper to ARC
This commit is contained in:
33
Code/ObjectMapping/RKMappingDescriptor.h
Normal file
33
Code/ObjectMapping/RKMappingDescriptor.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// RKMappingDescriptor.h
|
||||
// GateGuru
|
||||
//
|
||||
// Created by Blake Watters on 8/16/12.
|
||||
// Copyright (c) 2012 GateGuru, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <RestKit/RestKit.h>
|
||||
|
||||
//RKMakeStatusCodeRange(RKStatusCodeRangeSuccessful)
|
||||
// 200..299
|
||||
NSRange RKMakeSuccessfulStatusCodeRange(void);
|
||||
|
||||
// 400..499
|
||||
NSRange RKMakeClientErrorStatusCodeRange(void);
|
||||
|
||||
/**
|
||||
An RKMappingDescriptor object describes an object mapping configuration
|
||||
that is available for a given HTTP request.
|
||||
*/
|
||||
@interface RKMappingDescriptor : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) RKMapping *mapping; // required
|
||||
@property (nonatomic, strong, readonly) NSString *pathPattern; // can be nil
|
||||
@property (nonatomic, strong, readonly) NSString *keyPath; // can be nil
|
||||
@property (nonatomic, strong, readonly) NSIndexSet *statusCodes; // can be nil
|
||||
|
||||
+ (RKMappingDescriptor *)mappingDescriptorWithMapping:(RKMapping *)mapping
|
||||
pathPattern:(NSString *)pathPattern
|
||||
keyPath:(NSString *)keyPath
|
||||
statusCodes:(NSIndexSet *)statusCodes;
|
||||
@end
|
||||
82
Code/ObjectMapping/RKMappingDescriptor.m
Normal file
82
Code/ObjectMapping/RKMappingDescriptor.m
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// RKMappingDescriptor.m
|
||||
// GateGuru
|
||||
//
|
||||
// Created by Blake Watters on 8/16/12.
|
||||
// Copyright (c) 2012 GateGuru, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <RestKit/RKPathMatcher.h>
|
||||
#import "RKMappingDescriptor.h"
|
||||
|
||||
NSRange RKMakeSuccessfulStatusCodeRange(void)
|
||||
{
|
||||
return NSMakeRange(200, 100);
|
||||
}
|
||||
|
||||
NSRange RKMakeClientErrorStatusCodeRange(void)
|
||||
{
|
||||
return NSMakeRange(400, 100);
|
||||
}
|
||||
|
||||
// Cloned from AFStringFromIndexSet -- method should be non-static for reuse
|
||||
static NSString * RKStringFromIndexSet(NSIndexSet *indexSet) {
|
||||
NSMutableString *string = [NSMutableString string];
|
||||
|
||||
NSRange range = NSMakeRange([indexSet firstIndex], 1);
|
||||
while (range.location != NSNotFound) {
|
||||
NSUInteger nextIndex = [indexSet indexGreaterThanIndex:range.location];
|
||||
while (nextIndex == range.location + range.length) {
|
||||
range.length++;
|
||||
nextIndex = [indexSet indexGreaterThanIndex:nextIndex];
|
||||
}
|
||||
|
||||
if (string.length) {
|
||||
[string appendString:@","];
|
||||
}
|
||||
|
||||
if (range.length == 1) {
|
||||
[string appendFormat:@"%u", range.location];
|
||||
} else {
|
||||
NSUInteger firstIndex = range.location;
|
||||
NSUInteger lastIndex = firstIndex + range.length - 1;
|
||||
[string appendFormat:@"%u-%u", firstIndex, lastIndex];
|
||||
}
|
||||
|
||||
range.location = nextIndex;
|
||||
range.length = 1;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
@interface RKMappingDescriptor ()
|
||||
@property (nonatomic, strong, readwrite) RKMapping *mapping;
|
||||
@property (nonatomic, strong, readwrite) NSString *pathPattern;
|
||||
@property (nonatomic, strong, readwrite) NSString *keyPath;
|
||||
@property (nonatomic, strong, readwrite) NSIndexSet *statusCodes;
|
||||
@end
|
||||
|
||||
@implementation RKMappingDescriptor
|
||||
|
||||
+ (RKMappingDescriptor *)mappingDescriptorWithMapping:(RKMapping *)mapping
|
||||
pathPattern:(NSString *)pathPattern
|
||||
keyPath:(NSString *)keyPath
|
||||
statusCodes:(NSIndexSet *)statusCodes
|
||||
{
|
||||
RKMappingDescriptor *mappingDescriptor = [self new];
|
||||
mappingDescriptor.mapping = mapping;
|
||||
mappingDescriptor.pathPattern = pathPattern;
|
||||
mappingDescriptor.keyPath = keyPath;
|
||||
mappingDescriptor.statusCodes = statusCodes;
|
||||
|
||||
return mappingDescriptor;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: %p pathPattern=%@ keyPath=%@ statusCodes=%@ : %@>",
|
||||
NSStringFromClass([self class]), self, self.pathPattern, self.keyPath, RKStringFromIndexSet(self.statusCodes), self.mapping];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -32,19 +32,21 @@
|
||||
|
||||
@interface RKObjectMapper : NSObject
|
||||
|
||||
@property (nonatomic, readonly) id sourceObject;
|
||||
@property (nonatomic, assign) id targetObject;
|
||||
@property (nonatomic, readonly) RKObjectMappingProvider *mappingProvider;
|
||||
@property (nonatomic, strong, readonly) id sourceObject;
|
||||
@property (nonatomic, weak) id targetObject;
|
||||
@property (nonatomic, strong, readonly) RKObjectMappingProvider *mappingProvider;
|
||||
@property (nonatomic, strong, readwrite) NSDictionary *mappingsDictionary; // TODO: Becomes read-only...
|
||||
@property (nonatomic, assign) RKObjectMappingProviderContext context;
|
||||
@property (nonatomic, assign) id<RKObjectMapperDelegate> delegate;
|
||||
@property (nonatomic, weak) id<RKObjectMapperDelegate> delegate;
|
||||
@property (nonatomic, readonly) NSArray *errors;
|
||||
@property (nonatomic, retain) id<RKMappingOperationDataSource> mappingOperationDataSource;
|
||||
@property (nonatomic, strong) id<RKMappingOperationDataSource> mappingOperationDataSource;
|
||||
|
||||
+ (id)mapperWithObject:(id)object mappingProvider:(RKObjectMappingProvider *)mappingProvider;
|
||||
- (id)initWithObject:(id)object mappingProvider:(RKObjectMappingProvider *)mappingProvider;
|
||||
|
||||
- (id)initWithObject:(id)object mappingsDictionary:(NSDictionary *)mappingsDictionary;
|
||||
|
||||
// Primary entry point for the mapper. Examines the type of object and processes it appropriately...
|
||||
- (RKMappingResult *)performMapping;
|
||||
- (RKMappingResult *)performMapping:(NSError **)error;
|
||||
|
||||
@end
|
||||
|
||||
@@ -33,45 +33,45 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
|
||||
@interface RKObjectMapper ()
|
||||
|
||||
@property (nonatomic, retain) NSMutableArray *mappingErrors;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *mappingErrors;
|
||||
@property (nonatomic, strong) id sourceObject;
|
||||
@property (nonatomic, strong, readwrite) RKObjectMappingProvider *mappingProvider;
|
||||
//@property (nonatomic, strong, readwrite) NSDictionary *mappingsDictionary; // TODO: Becomes read-only
|
||||
@end
|
||||
|
||||
@implementation RKObjectMapper
|
||||
|
||||
@synthesize sourceObject = _sourceObject;
|
||||
@synthesize targetObject = _targetObject;
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize mappingProvider = _mappingProvider;
|
||||
@synthesize mappingOperationDataSource = _mappingOperationDataSource;
|
||||
@synthesize mappingErrors = _mappingErrors;
|
||||
@synthesize context = _context;
|
||||
|
||||
+ (id)mapperWithObject:(id)object mappingProvider:(RKObjectMappingProvider *)mappingProvider
|
||||
{
|
||||
return [[[self alloc] initWithObject:object mappingProvider:mappingProvider] autorelease];
|
||||
return [[self alloc] initWithObject:object mappingProvider:mappingProvider];
|
||||
}
|
||||
|
||||
- (id)initWithObject:(id)object mappingProvider:(RKObjectMappingProvider *)mappingProvider
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_sourceObject = [object retain];
|
||||
_mappingProvider = mappingProvider;
|
||||
_mappingErrors = [NSMutableArray new];
|
||||
_context = RKObjectMappingProviderContextObjectsByKeyPath;
|
||||
_mappingOperationDataSource = [RKObjectMappingOperationDataSource new];
|
||||
self.sourceObject = object;
|
||||
self.mappingProvider = mappingProvider;
|
||||
self.mappingErrors = [NSMutableArray new];
|
||||
self.context = RKObjectMappingProviderContextObjectsByKeyPath;
|
||||
self.mappingOperationDataSource = [RKObjectMappingOperationDataSource new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
- (id)initWithObject:(id)object mappingsDictionary:(NSDictionary *)mappingsDictionary;
|
||||
{
|
||||
[_sourceObject release];
|
||||
[_mappingErrors release];
|
||||
[_mappingOperationDataSource release];
|
||||
[super dealloc];
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.sourceObject = object;
|
||||
self.mappingsDictionary = mappingsDictionary;
|
||||
self.mappingErrors = [NSMutableArray new];
|
||||
self.context = RKObjectMappingProviderContextObjectsByKeyPath;
|
||||
self.mappingOperationDataSource = [RKObjectMappingOperationDataSource new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Errors
|
||||
@@ -97,7 +97,7 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
{
|
||||
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
errorMessage, NSLocalizedDescriptionKey,
|
||||
@"RKObjectMapperKeyPath", keyPath ? keyPath : (NSString *)[NSNull null],
|
||||
keyPath ? keyPath : [NSNull null], RKMappingErrorKeyPathErrorKey,
|
||||
nil];
|
||||
[userInfo addEntriesFromDictionary:otherInfo];
|
||||
NSError *error = [NSError errorWithDomain:RKErrorDomain code:errorCode userInfo:userInfo];
|
||||
@@ -258,6 +258,8 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
- (id)objectWithMapping:(RKMapping *)mapping andData:(id)mappableData
|
||||
{
|
||||
NSAssert([mapping isKindOfClass:[RKMapping class]], @"Expected an RKMapping object");
|
||||
NSAssert(self.mappingOperationDataSource, @"Cannot find or instantiate objects without a data source");
|
||||
|
||||
RKObjectMapping *objectMapping = nil;
|
||||
if ([mapping isKindOfClass:[RKDynamicMapping class]]) {
|
||||
objectMapping = [(RKDynamicMapping *)mapping objectMappingForDictionary:mappableData];
|
||||
@@ -271,7 +273,8 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
}
|
||||
|
||||
if (objectMapping) {
|
||||
return [self.mappingOperationDataSource objectForMappableContent:mappableData mapping:objectMapping];
|
||||
id object = [self.mappingOperationDataSource objectForMappableContent:mappableData mapping:objectMapping];
|
||||
return object;
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -301,7 +304,7 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
|
||||
RKLogTrace(@"Examining keyPath '%@' for mappable content...", keyPath);
|
||||
|
||||
if ([keyPath isEqualToString:@""]) {
|
||||
if ([keyPath isEqualToString:@""] || [keyPath isEqual:[NSNull null]]) {
|
||||
mappableValue = self.sourceObject;
|
||||
} else {
|
||||
mappableValue = [self.sourceObject valueForKeyPath:keyPath];
|
||||
@@ -340,7 +343,7 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
- (RKMappingResult *)performMapping:(NSError **)error
|
||||
{
|
||||
NSAssert(self.sourceObject != nil, @"Cannot perform object mapping without a source object to map from");
|
||||
NSAssert(self.mappingProvider != nil, @"Cannot perform object mapping without an object mapping provider");
|
||||
NSAssert(self.mappingProvider || self.mappingsDictionary, @"Cannot perform object mapping without an object mapping provider or dictionary of mappings");
|
||||
|
||||
RKLogDebug(@"Performing object mapping sourceObject: %@\n and targetObject: %@", self.sourceObject, self.targetObject);
|
||||
|
||||
@@ -353,22 +356,28 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
NSMutableDictionary *results = nil;
|
||||
|
||||
// Handle mapping selection for context
|
||||
id mappingsForContext = [self.mappingProvider valueForContext:self.context];
|
||||
if ([mappingsForContext isKindOfClass:[NSDictionary class]]) {
|
||||
results = [self performKeyPathMappingUsingMappingDictionary:mappingsForContext];
|
||||
if (self.mappingsDictionary) {
|
||||
results = [self performKeyPathMappingUsingMappingDictionary:self.mappingsDictionary];
|
||||
foundMappable = (results != nil);
|
||||
} else if ([mappingsForContext isKindOfClass:[RKMapping class]]) {
|
||||
id mappableData = self.sourceObject;
|
||||
if ([mappingsForContext rootKeyPath] != nil) {
|
||||
NSString *rootKeyPath = [mappingsForContext rootKeyPath];
|
||||
mappableData = [self.sourceObject valueForKeyPath:rootKeyPath];
|
||||
RKLogDebug(@"Selected object mapping has rootKeyPath. Apply valueForKeyPath to mappable data: %@", rootKeyPath);
|
||||
}
|
||||
} else {
|
||||
// Legacy RKObjectMappingProvider support...
|
||||
id mappingsForContext = [self.mappingProvider valueForContext:self.context];
|
||||
if ([mappingsForContext isKindOfClass:[NSDictionary class]]) {
|
||||
results = [self performKeyPathMappingUsingMappingDictionary:mappingsForContext];
|
||||
foundMappable = (results != nil);
|
||||
} else if ([mappingsForContext isKindOfClass:[RKMapping class]]) {
|
||||
id mappableData = self.sourceObject;
|
||||
if ([mappingsForContext rootKeyPath] != nil) {
|
||||
NSString *rootKeyPath = [mappingsForContext rootKeyPath];
|
||||
mappableData = [self.sourceObject valueForKeyPath:rootKeyPath];
|
||||
RKLogDebug(@"Selected object mapping has rootKeyPath. Apply valueForKeyPath to mappable data: %@", rootKeyPath);
|
||||
}
|
||||
|
||||
if (mappableData) {
|
||||
id mappingResult = [self performMappingForObject:mappableData atKeyPath:@"" usingMapping:mappingsForContext];
|
||||
foundMappable = YES;
|
||||
results = mappingResult ? [NSDictionary dictionaryWithObject:mappingResult forKey:@""] : nil;
|
||||
if (mappableData) {
|
||||
id mappingResult = [self performMappingForObject:mappableData atKeyPath:@"" usingMapping:mappingsForContext];
|
||||
foundMappable = YES;
|
||||
results = mappingResult ? [NSDictionary dictionaryWithObject:mappingResult forKey:@""] : nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user