mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-12 22:40:25 +08:00
Remove the mapping provider in favor of response descriptors
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
#import "RKAttributeMapping.h"
|
||||
#import "RKRelationshipMapping.h"
|
||||
#import "RKObjectSerializer.h"
|
||||
#import "RKObjectMappingProvider.h"
|
||||
#import "RKMappingResult.h"
|
||||
#import "RKObjectMapper.h"
|
||||
#import "RKParserRegistry.h"
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#import "RKObjectMapping.h"
|
||||
#import "RKMappingOperation.h"
|
||||
#import "RKMappingResult.h"
|
||||
#import "RKObjectMappingProvider.h"
|
||||
#import "RKMappingOperationDataSource.h"
|
||||
#import "RKErrors.h"
|
||||
#import "Support.h"
|
||||
@@ -34,16 +33,11 @@
|
||||
|
||||
@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, weak) id<RKObjectMapperDelegate> delegate;
|
||||
@property (nonatomic, readonly) NSArray *errors;
|
||||
@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...
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
#import "RKObjectMapper.h"
|
||||
#import "RKObjectMapper_Private.h"
|
||||
#import "RKObjectMappingProvider+Contexts.h"
|
||||
#import "RKObjectMappingOperationDataSource.h"
|
||||
#import "RKMappingErrors.h"
|
||||
#import "RKResponseDescriptor.h"
|
||||
#import "RKDynamicMapping.h"
|
||||
|
||||
NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
|
||||
@@ -35,31 +35,11 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
|
||||
@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
|
||||
|
||||
+ (id)mapperWithObject:(id)object mappingProvider:(RKObjectMappingProvider *)mappingProvider
|
||||
{
|
||||
return [[self alloc] initWithObject:object mappingProvider:mappingProvider];
|
||||
}
|
||||
|
||||
- (id)initWithObject:(id)object mappingProvider:(RKObjectMappingProvider *)mappingProvider
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.sourceObject = object;
|
||||
self.mappingProvider = mappingProvider;
|
||||
self.mappingErrors = [NSMutableArray new];
|
||||
self.context = RKObjectMappingProviderContextObjectsByKeyPath;
|
||||
self.mappingOperationDataSource = [RKObjectMappingOperationDataSource new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithObject:(id)object mappingsDictionary:(NSDictionary *)mappingsDictionary;
|
||||
{
|
||||
self = [super init];
|
||||
@@ -67,7 +47,6 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
self.sourceObject = object;
|
||||
self.mappingsDictionary = mappingsDictionary;
|
||||
self.mappingErrors = [NSMutableArray new];
|
||||
self.context = RKObjectMappingProviderContextObjectsByKeyPath;
|
||||
self.mappingOperationDataSource = [RKObjectMappingOperationDataSource new];
|
||||
}
|
||||
|
||||
@@ -343,7 +322,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 || self.mappingsDictionary, @"Cannot perform object mapping without an object mapping provider or dictionary of mappings");
|
||||
NSAssert(self.mappingsDictionary, @"Cannot perform object mapping without a dictionary of mappings");
|
||||
|
||||
RKLogDebug(@"Performing object mapping sourceObject: %@\n and targetObject: %@", self.sourceObject, self.targetObject);
|
||||
|
||||
@@ -353,33 +332,8 @@ NSString * const RKMappingErrorKeyPathErrorKey = @"keyPath";
|
||||
|
||||
// Perform the mapping
|
||||
BOOL foundMappable = NO;
|
||||
NSMutableDictionary *results = nil;
|
||||
|
||||
// Handle mapping selection for context
|
||||
if ([[self.mappingsDictionary allKeys] count] > 0) {
|
||||
results = [self performKeyPathMappingUsingMappingDictionary:self.mappingsDictionary];
|
||||
foundMappable = (results != nil);
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
NSMutableDictionary *results = [self performKeyPathMappingUsingMappingDictionary:self.mappingsDictionary];
|
||||
foundMappable = (results != nil);
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapperDidFinishMapping:)]) {
|
||||
[self.delegate mapperDidFinishMapping:self];
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
//
|
||||
// RKObjectMappingProvider.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 1/17/12.
|
||||
// Copyright (c) 2009-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 "RKObjectMappingProvider.h"
|
||||
|
||||
// Contexts provide primitives for managing collections of object mappings namespaced
|
||||
// within a single mapping provider. This enables easy reuse and extension via categories.
|
||||
@interface RKObjectMappingProvider (Contexts)
|
||||
|
||||
- (void)initializeContext:(RKObjectMappingProviderContext)context withValue:(id)value;
|
||||
- (id)valueForContext:(RKObjectMappingProviderContext)context;
|
||||
- (void)setValue:(id)value forContext:(RKObjectMappingProviderContext)context;
|
||||
|
||||
- (RKMapping *)mappingForContext:(RKObjectMappingProviderContext)context;
|
||||
/**
|
||||
Stores a single object mapping for a given context. Useful when a component needs to enable
|
||||
configuration via one (and only one) object mapping.
|
||||
*/
|
||||
- (void)setMapping:(RKMapping *)mapping context:(RKObjectMappingProviderContext)context;
|
||||
- (NSArray *)mappingsForContext:(RKObjectMappingProviderContext)context;
|
||||
- (void)addMapping:(RKMapping *)mapping context:(RKObjectMappingProviderContext)context;
|
||||
- (void)removeMapping:(RKMapping *)mapping context:(RKObjectMappingProviderContext)context;
|
||||
- (RKMapping *)mappingForKeyPath:(NSString *)keyPath context:(RKObjectMappingProviderContext)context;
|
||||
- (void)setMapping:(RKMapping *)mapping forKeyPath:(NSString *)keyPath context:(RKObjectMappingProviderContext)context;
|
||||
- (void)removeMappingForKeyPath:(NSString *)keyPath context:(RKObjectMappingProviderContext)context;
|
||||
|
||||
- (void)setMapping:(RKMapping *)mapping forPattern:(NSString *)pattern atIndex:(NSUInteger)index context:(RKObjectMappingProviderContext)context;
|
||||
- (void)setMapping:(RKMapping *)mapping forPattern:(NSString *)pattern context:(RKObjectMappingProviderContext)context;
|
||||
- (RKMapping *)mappingForPatternMatchingString:(NSString *)string context:(RKObjectMappingProviderContext)context;
|
||||
- (void)setEntry:(RKObjectMappingProviderContextEntry *)entry forPattern:(NSString *)pattern context:(RKObjectMappingProviderContext)context;
|
||||
- (RKObjectMappingProviderContextEntry *)entryForPatternMatchingString:(NSString *)string context:(RKObjectMappingProviderContext)context;
|
||||
|
||||
@end
|
||||
@@ -1,254 +0,0 @@
|
||||
//
|
||||
// RKObjectMappingProvider.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Jeremy Ellison on 5/6/11.
|
||||
// Copyright (c) 2009-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 "RKObjectMapping.h"
|
||||
#import "RKDynamicMapping.h"
|
||||
#import "RKObjectMappingProviderContextEntry.h"
|
||||
|
||||
// Internal framework contexts
|
||||
// @see RKObjectMappingProvider+Contexts.h
|
||||
typedef enum {
|
||||
RKObjectMappingProviderContextObjectsByKeyPath = 1000,
|
||||
RKObjectMappingProviderContextObjectsByType,
|
||||
RKObjectMappingProviderContextObjectsByResourcePathPattern,
|
||||
RKObjectMappingProviderContextSerialization,
|
||||
RKObjectMappingProviderContextErrors,
|
||||
RKObjectMappingProviderContextPagination
|
||||
} RKObjectMappingProviderContext;
|
||||
|
||||
/**
|
||||
The mapping provider is a repository of registered object mappings for use by instances
|
||||
of RKObjectManager and RKObjectMapper. It provides for the storage and retrieval of object
|
||||
mappings by keyPath and type.
|
||||
|
||||
The mapping provider is responsible for:
|
||||
|
||||
1. Providing instances of RKObjectMapper with keyPaths and object mappings for use
|
||||
when attempting to map a parsed payload into objects. Each keyPath is examined using
|
||||
valueForKeyPath: to determine if any mappable data exists within the payload. If data is
|
||||
found, the RKObjectMapper will instantiate an RKObjectMappingOperation to perform the mapping
|
||||
using the RKObjectMapping or RKDynamicMapping associated with the keyPath.
|
||||
1. Providing the appropriate serialization mapping to instances of RKObjectManager when an object
|
||||
is to be sent to the remote server using [RKObjectManager postObject:delegate:] or
|
||||
[RKObjectManager postObject:delegate]. This mapping is used to serialize the object into a
|
||||
format suitable for encoding into a URL form encoded or JSON representation.
|
||||
1. Providing convenient storage of RKObjectMapping references for users who are not using keyPath
|
||||
based mapping. Mappings can be added to the provider and retrieved by the [RKObjectMapping objectClass]
|
||||
that they target.
|
||||
*/
|
||||
@interface RKObjectMappingProvider : NSObject {
|
||||
NSMutableDictionary *mappingContexts;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates and returns an autoreleased RKObjectMappingProvider instance.
|
||||
|
||||
@return A new autoreleased object mapping provider instance.
|
||||
*/
|
||||
+ (id)mappingProvider;
|
||||
|
||||
/**
|
||||
Instantiate and return a new auto-released object mapping provider after
|
||||
yielding it to the specified block for configuration
|
||||
*/
|
||||
+ (id)mappingProviderUsingBlock:(void (^)(RKObjectMappingProvider *))block;
|
||||
|
||||
/**
|
||||
Configures the mapping provider to use the RKObjectMapping or RKDynamicMapping provided when
|
||||
content is encountered at the specified keyPath.
|
||||
|
||||
When an RKObjectMapper is performing its work, each registered keyPath within the mapping provider will
|
||||
be searched for content in the parsed payload. If mappable content is found, the object mapping configured
|
||||
for the keyPath will be used to perform an RKObjectMappingOperation.
|
||||
|
||||
@param objectOrDynamicMapping An RKObjectMapping or RKDynamicMapping to register for keyPath based mapping.
|
||||
@param keyPath The keyPath to register the mapping as being responsible for mapping.
|
||||
@see RKObjectMapper
|
||||
@see RKObjectMappingOperation
|
||||
*/
|
||||
- (void)setObjectMapping:(RKMapping *)objectOrDynamicMapping forKeyPath:(NSString *)keyPath;
|
||||
|
||||
/**
|
||||
Returns the RKObjectMapping or RKObjectDynamic mapping configured for use
|
||||
when mappable content is encountered at keyPath
|
||||
|
||||
@param keyPath A registered keyPath to retrieve the object mapping for
|
||||
@return The RKObjectMapping or RKDynamicMapping for the specified keyPath or nil if none is registered.
|
||||
*/
|
||||
- (RKMapping *)objectMappingForKeyPath:(NSString *)keyPath;
|
||||
|
||||
/**
|
||||
Removes the RKObjectMapping or RKDynamicMapping registered at the specified keyPath
|
||||
from the provider.
|
||||
|
||||
@param keyPath The keyPath to remove the corresponding mapping for
|
||||
*/
|
||||
- (void)removeObjectMappingForKeyPath:(NSString *)keyPath;
|
||||
|
||||
/**
|
||||
Returns a dictionary where the keys are mappable keyPaths and the values are the RKObjectMapping
|
||||
or RKDynamicMapping to use for mappable data that appears at the keyPath.
|
||||
|
||||
@warning The returned dictionary can contain RKDynamicMapping instances. Check the type if
|
||||
you are using dynamic mapping.
|
||||
@return A dictionary of all registered keyPaths and their corresponding object mapping instances
|
||||
*/
|
||||
- (NSDictionary *)objectMappingsByKeyPath;
|
||||
|
||||
/**
|
||||
Adds an object mapping to the provider for later retrieval. The mapping is not bound to a particular keyPath and
|
||||
must be explicitly set on an instance of RKObjectLoader or RKObjectMappingOperation to be applied. This is useful
|
||||
in cases where the remote system does not namespace resources in a keyPath that can be used for disambiguation.
|
||||
|
||||
You can retrieve mappings added to the provider by invoking objectMappingsForClass: and objectMappingForClass:
|
||||
|
||||
@param objectMapping An object mapping instance we wish to register with the provider.
|
||||
@see objectMappingsForClass:
|
||||
@see objectMappingForClass:
|
||||
*/
|
||||
- (void)addObjectMapping:(RKObjectMapping *)objectMapping;
|
||||
|
||||
/**
|
||||
Returns all object mappings registered for a particular class on the provider. The collection of mappings is assembled
|
||||
by searching for all mappings added via addObjctMapping: and then consulting those registered via objectMappingForKeyPath:
|
||||
|
||||
@param objectClass The class we want to retrieve the mappings for
|
||||
@return An array of all object mappings matching the objectClass. Can be empty.
|
||||
*/
|
||||
- (NSArray *)objectMappingsForClass:(Class)objectClass;
|
||||
|
||||
/**
|
||||
Returns the first object mapping for a objectClass registered in the provider.
|
||||
|
||||
The objectClass is the class for a model you use to represent data retrieved in
|
||||
XML or JSON format. For example, if we were developing a Twitter application we
|
||||
might have an objectClass of RKTweet for storing Tweet data. We could retrieve
|
||||
the object mapping for this model by invoking
|
||||
`[mappingProvider objectMappingForClass:[RKTweet class]];`
|
||||
|
||||
Mappings registered via addObjectMapping: take precedence over those registered
|
||||
via setObjectMapping:forKeyPath:.
|
||||
|
||||
@param objectClass The class that we want to return mappings for
|
||||
@return An RKObjectMapping matching objectClass or nil
|
||||
*/
|
||||
- (RKObjectMapping *)objectMappingForClass:(Class)objectClass;
|
||||
|
||||
/**
|
||||
Registers an object mapping for use when serializing instances of objectClass for transport
|
||||
over HTTP. Used by the object manager during postObject: and putObject:.
|
||||
|
||||
Serialization mappings are simply instances of RKObjectMapping that target NSMutableDictionary
|
||||
as the target object class. After the object is mapped into an NSMutableDictionary, it can be
|
||||
encoded to form encoded string, JSON, XML, etc.
|
||||
|
||||
@param objectMapping The serialization mapping to register for use when serializing objectClass
|
||||
@param objectClass The class of the object type we are registering a serialization for
|
||||
@see [RKObjectMapping serializationMapping]
|
||||
*/
|
||||
- (void)setSerializationMapping:(RKObjectMapping *)objectMapping forClass:(Class)objectClass;
|
||||
|
||||
/**
|
||||
Returns the serialization mapping for a specific object class
|
||||
which has been previously registered.
|
||||
|
||||
@param objectClass The class we wish to obtain the serialization mapping for
|
||||
@return The RKObjectMapping instance used for mapping instances of objectClass for transport
|
||||
@see setSerializationMapping:forClass:
|
||||
*/
|
||||
- (RKObjectMapping *)serializationMappingForClass:(Class)objectClass;
|
||||
|
||||
/**
|
||||
Configures an object mapping to be used when during a load event where the resourcePath of
|
||||
the RKObjectLoader instance matches resourcePathPattern.
|
||||
|
||||
The resourcePathPattern is a SOCKit pattern matching property names preceded by colons within
|
||||
a path. For example, if a collection of reviews for a product were loaded from a remote system
|
||||
at the resourcePath @"/products/1234/reviews", object mapping could be configured to handle
|
||||
this request with a resourcePathPattern of @"/products/:productID/reviews".
|
||||
|
||||
**NOTE** that care must be taken when configuring patterns within the provider. The patterns
|
||||
will be evaluated in the order they are added to the provider, so more specific patterns must
|
||||
precede more general patterns where either would generate a match.
|
||||
|
||||
@param objectMapping The object mapping to use when the resourcePath matches the specified
|
||||
resourcePathPattern.
|
||||
@param resourcePathPattern A pattern to be evaluated using an RKPathMatcher against a resourcePath
|
||||
to determine if objectMapping is the appropriate mapping.
|
||||
@see RKPathMatcher
|
||||
@see RKURL
|
||||
@see RKObjectLoader
|
||||
*/
|
||||
- (void)setObjectMapping:(RKMapping *)objectMapping forResourcePathPattern:(NSString *)resourcePathPattern;
|
||||
|
||||
/**
|
||||
Returns the first objectMapping configured in the provider with a resourcePathPattern matching
|
||||
the specified resourcePath.
|
||||
|
||||
@param resourcePath A resource path to retrieve the first RKObjectMapping or RKDynamicMapping
|
||||
configured with a matching pattern.
|
||||
@return An RKObjectMapping or RKDynamicMapping for a resource path pattern matching resourcePath
|
||||
or nil if no match was found.
|
||||
*/
|
||||
- (RKMapping *)objectMappingForResourcePath:(NSString *)resourcePath;
|
||||
|
||||
|
||||
- (void)setEntry:(RKObjectMappingProviderContextEntry *)entry forResourcePathPattern:(NSString *)resourcePath;
|
||||
- (RKObjectMappingProviderContextEntry *)entryForResourcePath:(NSString *)resourcePath;
|
||||
- (RKObjectMappingProviderContextEntry *)entryForResourcePathPattern:(NSString *)resourcePathPattern;
|
||||
- (RKMapping *)objectMappingForResourcePathPattern:(NSString *)resourcePathPattern;
|
||||
|
||||
/**
|
||||
An object mapping used when the remote system returns an error status code
|
||||
and a payload with a MIME Type that RestKit is capable of parsing.
|
||||
|
||||
@see RKObjectLoader
|
||||
@see RKParserRegistry
|
||||
*/
|
||||
@property (nonatomic, retain) RKObjectMapping *errorMapping;
|
||||
|
||||
/**
|
||||
An object mapping used when mapping pagination metadata (current page, object count, etc)
|
||||
during a paginated object loading operation. The objectClass of the paginationMapping must
|
||||
be RKObjectPaginator.
|
||||
|
||||
For example, if using the popular will_paginate plugin with Ruby on Rails, we would configure
|
||||
our pagination mapping like so:
|
||||
|
||||
// Assumes the JSON format of http://stackoverflow.com/questions/4699182/will-paginate-json-support
|
||||
RKObjectMapping *paginationMapping = [RKObjectMapping mappingForClass:[RKObjectPaginator class]];
|
||||
[paginationMapping mapKeyPath:@"current_page" toAttribute:@"currentPage"];
|
||||
[paginationMapping mapKeyPath:@"per_page" toAttribute:@"perPage"];
|
||||
[paginationMapping mapKeyPath:@"total_entries" toAttribute:@"objectCount"];
|
||||
|
||||
@see RKObjectPaginator
|
||||
*/
|
||||
@property (nonatomic, retain) RKObjectMapping *paginationMapping;
|
||||
|
||||
@end
|
||||
|
||||
// Method signatures being phased out
|
||||
@interface RKObjectMappingProvider (Deprecations)
|
||||
+ (RKObjectMappingProvider *)objectMappingProvider;
|
||||
- (void)setMapping:(RKMapping *)objectOrDynamicMapping forKeyPath:(NSString *)keyPath;
|
||||
- (RKMapping *)mappingForKeyPath:(NSString *)keyPath;
|
||||
- (NSDictionary *)mappingsByKeyPath;
|
||||
- (void)removeMappingForKeyPath:(NSString *)keyPath;
|
||||
@end
|
||||
@@ -1,378 +0,0 @@
|
||||
//
|
||||
// RKObjectMappingProvider.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Jeremy Ellison on 5/6/11.
|
||||
// Copyright (c) 2009-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 "RKObjectMappingProvider.h"
|
||||
#import "RKObjectMappingProvider+Contexts.h"
|
||||
#import "RKOrderedDictionary.h"
|
||||
#import "RKPathMatcher.h"
|
||||
#import "RKObjectMappingProviderContextEntry.h"
|
||||
#import "RKErrorMessage.h"
|
||||
|
||||
@implementation RKObjectMappingProvider
|
||||
|
||||
+ (RKObjectMappingProvider *)mappingProvider
|
||||
{
|
||||
return [[self new] autorelease];
|
||||
}
|
||||
|
||||
+ (RKObjectMappingProvider *)mappingProviderUsingBlock:(void (^)(RKObjectMappingProvider *mappingProvider))block
|
||||
{
|
||||
RKObjectMappingProvider *mappingProvider = [self mappingProvider];
|
||||
block(mappingProvider);
|
||||
return mappingProvider;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
mappingContexts = [NSMutableDictionary new];
|
||||
[self initializeContext:RKObjectMappingProviderContextObjectsByKeyPath withValue:[NSMutableDictionary dictionary]];
|
||||
[self initializeContext:RKObjectMappingProviderContextObjectsByType withValue:[NSMutableArray array]];
|
||||
[self initializeContext:RKObjectMappingProviderContextObjectsByResourcePathPattern withValue:[RKOrderedDictionary dictionary]];
|
||||
[self initializeContext:RKObjectMappingProviderContextSerialization withValue:[NSMutableDictionary dictionary]];
|
||||
[self initializeContext:RKObjectMappingProviderContextErrors withValue:[NSNull null]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mappingContexts release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setObjectMapping:(RKMapping *)objectOrDynamicMapping forKeyPath:(NSString *)keyPath
|
||||
{
|
||||
[self setMapping:objectOrDynamicMapping forKeyPath:keyPath context:RKObjectMappingProviderContextObjectsByKeyPath];
|
||||
}
|
||||
|
||||
- (void)removeObjectMappingForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
[self removeMappingForKeyPath:keyPath context:RKObjectMappingProviderContextObjectsByKeyPath];
|
||||
}
|
||||
|
||||
- (RKMapping *)objectMappingForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
return [self mappingForKeyPath:keyPath context:RKObjectMappingProviderContextObjectsByKeyPath];
|
||||
}
|
||||
|
||||
- (void)setSerializationMapping:(RKObjectMapping *)mapping forClass:(Class)objectClass
|
||||
{
|
||||
[self setMapping:mapping forKeyPath:NSStringFromClass(objectClass) context:RKObjectMappingProviderContextSerialization];
|
||||
}
|
||||
|
||||
- (RKObjectMapping *)serializationMappingForClass:(Class)objectClass
|
||||
{
|
||||
return (RKObjectMapping *)[self mappingForKeyPath:NSStringFromClass(objectClass) context:RKObjectMappingProviderContextSerialization];
|
||||
}
|
||||
|
||||
- (NSDictionary *)objectMappingsByKeyPath
|
||||
{
|
||||
return [NSDictionary dictionaryWithDictionary:(NSDictionary *)[self valueForContext:RKObjectMappingProviderContextObjectsByKeyPath]];
|
||||
}
|
||||
|
||||
- (void)addObjectMapping:(RKObjectMapping *)objectMapping
|
||||
{
|
||||
[self addMapping:objectMapping context:RKObjectMappingProviderContextObjectsByType];
|
||||
}
|
||||
|
||||
- (NSArray *)objectMappingsForClass:(Class)theClass
|
||||
{
|
||||
NSMutableArray *mappings = [NSMutableArray array];
|
||||
NSArray *mappingByType = [self valueForContext:RKObjectMappingProviderContextObjectsByType];
|
||||
NSArray *mappingByKeyPath = [[self valueForContext:RKObjectMappingProviderContextObjectsByKeyPath] allValues];
|
||||
NSArray *mappingsToSearch = [[NSArray arrayWithArray:mappingByType] arrayByAddingObjectsFromArray:mappingByKeyPath];
|
||||
for (RKMapping *candidateMapping in mappingsToSearch) {
|
||||
if (![candidateMapping respondsToSelector:@selector(objectClass)] || [mappings containsObject:candidateMapping])
|
||||
continue;
|
||||
Class mappedClass = [candidateMapping performSelector:@selector(objectClass)];
|
||||
if (mappedClass && [NSStringFromClass(mappedClass) isEqualToString:NSStringFromClass(theClass)]) {
|
||||
[mappings addObject:candidateMapping];
|
||||
}
|
||||
}
|
||||
return [NSArray arrayWithArray:mappings];
|
||||
}
|
||||
|
||||
- (RKObjectMapping *)objectMappingForClass:(Class)theClass
|
||||
{
|
||||
NSArray *objectMappings = [self objectMappingsForClass:theClass];
|
||||
return ([objectMappings count] > 0) ? [objectMappings objectAtIndex:0] : nil;
|
||||
}
|
||||
|
||||
#pragma mark - Error Mappings
|
||||
|
||||
- (RKObjectMapping *)errorMapping
|
||||
{
|
||||
return (RKObjectMapping *)[self mappingForContext:RKObjectMappingProviderContextErrors];
|
||||
}
|
||||
|
||||
- (void)setErrorMapping:(RKObjectMapping *)errorMapping
|
||||
{
|
||||
if (errorMapping) {
|
||||
[self setMapping:errorMapping context:RKObjectMappingProviderContextErrors];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Pagination Mapping
|
||||
|
||||
- (RKObjectMapping *)paginationMapping
|
||||
{
|
||||
return (RKObjectMapping *)[self mappingForContext:RKObjectMappingProviderContextPagination];
|
||||
}
|
||||
|
||||
- (void)setPaginationMapping:(RKObjectMapping *)paginationMapping
|
||||
{
|
||||
[self setMapping:paginationMapping context:RKObjectMappingProviderContextPagination];
|
||||
}
|
||||
|
||||
- (void)setObjectMapping:(RKMapping *)objectMapping forResourcePathPattern:(NSString *)resourcePath
|
||||
{
|
||||
[self setMapping:objectMapping forPattern:resourcePath context:RKObjectMappingProviderContextObjectsByResourcePathPattern];
|
||||
}
|
||||
|
||||
- (RKMapping *)objectMappingForResourcePath:(NSString *)resourcePath
|
||||
{
|
||||
return [self mappingForPatternMatchingString:resourcePath context:RKObjectMappingProviderContextObjectsByResourcePathPattern];
|
||||
}
|
||||
|
||||
- (void)setEntry:(RKObjectMappingProviderContextEntry *)entry forResourcePathPattern:(NSString *)resourcePath
|
||||
{
|
||||
[self setEntry:entry forPattern:resourcePath context:RKObjectMappingProviderContextObjectsByResourcePathPattern];
|
||||
}
|
||||
|
||||
- (RKObjectMappingProviderContextEntry *)entryForResourcePath:(NSString *)resourcePath
|
||||
{
|
||||
return [self entryForPatternMatchingString:resourcePath context:RKObjectMappingProviderContextObjectsByResourcePathPattern];
|
||||
}
|
||||
|
||||
- (RKObjectMappingProviderContextEntry *)entryForResourcePathPattern:(NSString *)resourcePathPattern {
|
||||
RKOrderedDictionary *contextValue = [self valueForContext:RKObjectMappingProviderContextObjectsByResourcePathPattern];
|
||||
for (NSString *pattern in contextValue) {
|
||||
if ([pattern isEqualToString:resourcePathPattern]) {
|
||||
return [contextValue objectForKey:pattern];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (RKMapping *)objectMappingForResourcePathPattern:(NSString *)resourcePathPattern {
|
||||
RKObjectMappingProviderContextEntry *entry = [self entryForResourcePathPattern:resourcePathPattern];
|
||||
return entry.mapping;
|
||||
}
|
||||
|
||||
#pragma mark - Mapping Context Primitives
|
||||
|
||||
- (void)initializeContext:(RKObjectMappingProviderContext)context withValue:(id)value
|
||||
{
|
||||
NSAssert([self valueForContext:context] == nil, @"Attempt to reinitialized an existing mapping provider context.");
|
||||
[self setValue:value forContext:context];
|
||||
}
|
||||
|
||||
- (id)valueForContext:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSNumber *contextNumber = [NSNumber numberWithInteger:context];
|
||||
return [mappingContexts objectForKey:contextNumber];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)value forContext:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSNumber *contextNumber = [NSNumber numberWithInteger:context];
|
||||
[mappingContexts setObject:value forKey:contextNumber];
|
||||
}
|
||||
|
||||
- (void)assertStorageForContext:(RKObjectMappingProviderContext)context isKindOfClass:(Class)theClass
|
||||
{
|
||||
id contextValue = [self valueForContext:context];
|
||||
NSAssert([contextValue isKindOfClass:theClass], @"Storage type mismatch for context %d: expected a %@, got %@.", context, theClass, [contextValue class]);
|
||||
}
|
||||
|
||||
- (void)setMapping:(RKMapping *)mapping context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSNumber *contextNumber = [NSNumber numberWithInteger:context];
|
||||
[mappingContexts setObject:mapping forKey:contextNumber];
|
||||
}
|
||||
|
||||
- (RKMapping *)mappingForContext:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
id contextValue = [self valueForContext:context];
|
||||
if ([contextValue isEqual:[NSNull null]]) return nil;
|
||||
Class class = [RKMapping class];
|
||||
NSAssert([contextValue isKindOfClass:class], @"Storage type mismatch for context %d: expected a %@, got %@.", context, class, [contextValue class]);
|
||||
return contextValue;
|
||||
}
|
||||
|
||||
- (NSArray *)mappingsForContext:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
id contextValue = [self valueForContext:context];
|
||||
if (contextValue == nil) return [NSArray array];
|
||||
[self assertStorageForContext:context isKindOfClass:[NSArray class]];
|
||||
|
||||
return [NSArray arrayWithArray:contextValue];
|
||||
}
|
||||
|
||||
- (void)addMapping:(RKMapping *)mapping context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSMutableArray *contextValue = [self valueForContext:context];
|
||||
if (contextValue == nil) {
|
||||
contextValue = [NSMutableArray arrayWithCapacity:1];
|
||||
[self setValue:contextValue forContext:context];
|
||||
}
|
||||
[self assertStorageForContext:context isKindOfClass:[NSArray class]];
|
||||
[contextValue addObject:mapping];
|
||||
}
|
||||
|
||||
- (void)removeMapping:(RKMapping *)mapping context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSMutableArray *contextValue = [self valueForContext:context];
|
||||
NSAssert(contextValue, @"Attempted to remove mapping from undefined context: %d", context);
|
||||
[self assertStorageForContext:context isKindOfClass:[NSArray class]];
|
||||
NSAssert([contextValue containsObject:mapping], @"Attempted to remove mapping from collection that does not include it for context: %d", context);
|
||||
[contextValue removeObject:mapping];
|
||||
}
|
||||
|
||||
- (RKMapping *)mappingForKeyPath:(NSString *)keyPath context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSMutableDictionary *contextValue = [self valueForContext:context];
|
||||
NSAssert(contextValue, @"Attempted to retrieve mapping from undefined context: %d", context);
|
||||
[self assertStorageForContext:context isKindOfClass:[NSDictionary class]];
|
||||
return [contextValue valueForKey:keyPath];
|
||||
}
|
||||
|
||||
- (void)setMapping:(RKMapping *)mapping forKeyPath:(NSString *)keyPath context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSMutableDictionary *contextValue = [self valueForContext:context];
|
||||
if (contextValue == nil) {
|
||||
contextValue = [NSMutableDictionary dictionary];
|
||||
[self setValue:contextValue forContext:context];
|
||||
}
|
||||
[self assertStorageForContext:context isKindOfClass:[NSDictionary class]];
|
||||
[contextValue setValue:mapping forKey:keyPath];
|
||||
}
|
||||
|
||||
- (void)removeMappingForKeyPath:(NSString *)keyPath context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSMutableDictionary *contextValue = [self valueForContext:context];
|
||||
[self assertStorageForContext:context isKindOfClass:[NSDictionary class]];
|
||||
[contextValue removeObjectForKey:keyPath];
|
||||
}
|
||||
|
||||
- (void)setMapping:(RKMapping *)mapping forPattern:(NSString *)pattern atIndex:(NSUInteger)index context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
RKOrderedDictionary *contextValue = [self valueForContext:context];
|
||||
if (contextValue == nil) {
|
||||
contextValue = [RKOrderedDictionary dictionary];
|
||||
[self setValue:contextValue forContext:context];
|
||||
}
|
||||
[self assertStorageForContext:context isKindOfClass:[RKOrderedDictionary class]];
|
||||
[contextValue insertObject:[RKObjectMappingProviderContextEntry contextEntryWithMapping:mapping]
|
||||
forKey:pattern
|
||||
atIndex:index];
|
||||
}
|
||||
|
||||
- (void)setMapping:(RKMapping *)mapping forPattern:(NSString *)pattern context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
RKOrderedDictionary *contextValue = [self valueForContext:context];
|
||||
if (contextValue == nil) {
|
||||
contextValue = [RKOrderedDictionary dictionary];
|
||||
[self setValue:contextValue forContext:context];
|
||||
}
|
||||
[self assertStorageForContext:context isKindOfClass:[RKOrderedDictionary class]];
|
||||
[contextValue setObject:[RKObjectMappingProviderContextEntry contextEntryWithMapping:mapping]
|
||||
forKey:pattern];
|
||||
}
|
||||
|
||||
- (RKMapping *)mappingForPatternMatchingString:(NSString *)string context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
NSAssert(string, @"Cannot look up mapping matching nil pattern string.");
|
||||
RKOrderedDictionary *contextValue = [self valueForContext:context];
|
||||
NSAssert(contextValue, @"Attempted to retrieve mapping from undefined context: %d", context);
|
||||
for (NSString *pattern in contextValue) {
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher matcherWithPattern:pattern];
|
||||
if ([pathMatcher matchesPath:string tokenizeQueryStrings:NO parsedArguments:nil]) {
|
||||
RKObjectMappingProviderContextEntry *entry = [contextValue objectForKey:pattern];
|
||||
return entry.mapping;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setEntry:(RKObjectMappingProviderContextEntry *)entry forPattern:(NSString *)pattern context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
RKOrderedDictionary *contextValue = [self valueForContext:context];
|
||||
if (contextValue == nil) {
|
||||
contextValue = [RKOrderedDictionary dictionary];
|
||||
[self setValue:contextValue forContext:context];
|
||||
}
|
||||
[self assertStorageForContext:context isKindOfClass:[RKOrderedDictionary class]];
|
||||
[contextValue setObject:entry
|
||||
forKey:pattern];
|
||||
}
|
||||
|
||||
- (RKObjectMappingProviderContextEntry *)entryForPatternMatchingString:(NSString *)string context:(RKObjectMappingProviderContext)context
|
||||
{
|
||||
RKOrderedDictionary *contextValue = [self valueForContext:context];
|
||||
NSAssert(contextValue, @"Attempted to retrieve mapping from undefined context: %d", context);
|
||||
for (NSString *pattern in contextValue) {
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher matcherWithPattern:pattern];
|
||||
if ([pathMatcher matchesPath:string tokenizeQueryStrings:NO parsedArguments:nil]) {
|
||||
return [contextValue objectForKey:pattern];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - Aliases
|
||||
|
||||
+ (RKObjectMappingProvider *)objectMappingProvider
|
||||
{
|
||||
return [self mappingProvider];
|
||||
}
|
||||
|
||||
- (RKObjectMapping *)mappingForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
return (RKObjectMapping *)[self objectMappingForKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (void)setMapping:(RKObjectMapping *)mapping forKeyPath:(NSString *)keyPath
|
||||
{
|
||||
[self setObjectMapping:mapping forKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (NSDictionary *)mappingsByKeyPath
|
||||
{
|
||||
return [self objectMappingsByKeyPath];
|
||||
}
|
||||
|
||||
- (void)removeMappingForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
[self removeObjectMappingForKeyPath:keyPath];
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
+ (id)mappingProviderWithBlock:(void (^)(RKObjectMappingProvider *))block
|
||||
{
|
||||
return [self mappingProviderUsingBlock:block];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,19 +0,0 @@
|
||||
//
|
||||
// RKObjectMappingProviderContextEntry.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Jeff Arena on 1/26/12.
|
||||
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKMapping.h"
|
||||
|
||||
@interface RKObjectMappingProviderContextEntry : NSObject
|
||||
|
||||
+ (RKObjectMappingProviderContextEntry *)contextEntryWithMapping:(RKMapping *)mapping;
|
||||
+ (RKObjectMappingProviderContextEntry *)contextEntryWithMapping:(RKMapping *)mapping userData:(id)userData;
|
||||
|
||||
@property (nonatomic, retain) RKMapping *mapping;
|
||||
@property (nonatomic, retain) id userData;
|
||||
|
||||
@end
|
||||
@@ -1,66 +0,0 @@
|
||||
//
|
||||
// RKObjectMappingProviderContextEntry.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Jeff Arena on 1/26/12.
|
||||
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKObjectMappingProviderContextEntry.h"
|
||||
|
||||
@implementation RKObjectMappingProviderContextEntry
|
||||
|
||||
@synthesize mapping = _mapping;
|
||||
@synthesize userData = _userData;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_mapping = nil;
|
||||
_userData = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_mapping release];
|
||||
_mapping = nil;
|
||||
[_userData release];
|
||||
_userData = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if ([object isKindOfClass:[RKObjectMappingProviderContextEntry class]]) {
|
||||
RKObjectMappingProviderContextEntry *entry = (RKObjectMappingProviderContextEntry *)object;
|
||||
return ([self.mapping isEqual:entry.mapping] && (self.userData == entry.userData));
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
NSUInteger prime = 31;
|
||||
NSUInteger result = 1;
|
||||
result = prime *[self.userData hash] ? [self.mapping hash] : [self.userData hash];
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (RKObjectMappingProviderContextEntry *)contextEntryWithMapping:(RKMapping *)mapping
|
||||
{
|
||||
RKObjectMappingProviderContextEntry *contextEntry = [[[RKObjectMappingProviderContextEntry alloc] init] autorelease];
|
||||
contextEntry.mapping = mapping;
|
||||
return contextEntry;
|
||||
}
|
||||
|
||||
+ (RKObjectMappingProviderContextEntry *)contextEntryWithMapping:(RKMapping *)mapping userData:(id)userData
|
||||
{
|
||||
RKObjectMappingProviderContextEntry *contextEntry = [RKObjectMappingProviderContextEntry contextEntryWithMapping:mapping];
|
||||
contextEntry.userData = userData;
|
||||
return contextEntry;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user