Skip to content

Commit

Permalink
Renamed metadata.mapping to metadata.network
Browse files Browse the repository at this point in the history
  • Loading branch information
batjo committed Feb 5, 2015
1 parent dfb660a commit bfa35e6
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 5 deletions.
10 changes: 10 additions & 0 deletions Code/Network/RKResponseDescriptor.h
Expand Up @@ -158,6 +158,16 @@
*/
- (BOOL)matchesResponse:(NSHTTPURLResponse *)response;

/**
Returns a Dictionary of parsed arguments extracted from the URL of the given response object.
@param response The HTTP response object to compare with the base URL, path pattern, and status codes set of the receiver.
@return A dictionary of parsed arguments if the response matches the base URL, path pattern, and status codes set of the receiver, else `nil`.
@see `matchesResponse:`
*/
- (NSDictionary *)parsedArgumentsFromResponse:(NSHTTPURLResponse *)response;

///-------------------------
/// @name Comparing Response Descriptors
///-------------------------
Expand Down
37 changes: 32 additions & 5 deletions Code/Network/RKResponseDescriptor.m
Expand Up @@ -115,32 +115,48 @@ - (NSString *)description
}

- (BOOL)matchesPath:(NSString *)path
{
return [self matchesPath:path parsedArguments:nil];
}

- (BOOL)matchesPath:(NSString *)path parsedArguments:(NSDictionary **)outParsedArguments
{
if (!self.pathPattern || !path) return YES;
return [self.pathPatternMatcher matchesPath:path tokenizeQueryStrings:NO parsedArguments:nil];
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:self.pathPattern];
return [pathMatcher matchesPath:path tokenizeQueryStrings:NO parsedArguments:outParsedArguments];
}

- (BOOL)matchesURL:(NSURL *)URL
{
return [self matchesURL:URL parsedArguments:nil];
}

- (BOOL)matchesURL:(NSURL *)URL parsedArguments:(NSDictionary **)outParsedArguments
{
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(URL, self.baseURL);
if (self.baseURL) {
if (! RKURLIsRelativeToURL(URL, self.baseURL)) return NO;
return [self matchesPath:pathAndQueryString];
return [self matchesPath:pathAndQueryString parsedArguments:outParsedArguments];
} else {
return [self matchesPath:pathAndQueryString];
return [self matchesPath:pathAndQueryString parsedArguments:outParsedArguments];
}
}

- (BOOL)matchesResponse:(NSHTTPURLResponse *)response
{
if (! [self matchesURL:response.URL]) return NO;
return [self matchesResponse:response parsedArguments:nil];
}

- (BOOL)matchesResponse:(NSHTTPURLResponse *)response parsedArguments:(NSDictionary **)outParsedArguments
{
if (![self matchesURL:response.URL parsedArguments:outParsedArguments]) return NO;

if (self.statusCodes) {
if (! [self.statusCodes containsIndex:response.statusCode]) {
return NO;
}
}

return YES;
}

Expand All @@ -149,6 +165,17 @@ - (BOOL)matchesMethod:(RKRequestMethod)method
return self.method & method;
}

- (NSDictionary *)parsedArgumentsFromResponse:(NSHTTPURLResponse *)response
{
NSDictionary *parsedArguments = nil;
if ([self matchesResponse:response parsedArguments:&parsedArguments])
{
return parsedArguments;
}

return nil;
}

- (BOOL)isEqual:(id)object
{
if (self == object) {
Expand Down
32 changes: 32 additions & 0 deletions Code/Network/RKResponseMapperOperation.m
Expand Up @@ -132,6 +132,7 @@ @interface RKResponseMapperOperation ()
@property (nonatomic, strong, readwrite) NSError *error;
@property (nonatomic, strong, readwrite) NSArray *matchingResponseDescriptors;
@property (nonatomic, strong, readwrite) NSDictionary *responseMappingsDictionary;
@property (nonatomic, strong, readwrite) NSDictionary *responseMappingArgumentsDictionary;
@property (nonatomic, strong) RKMapperOperation *mapperOperation;
@property (nonatomic, copy) id (^willMapDeserializedResponseBlock)(id);
@property (nonatomic, copy) void(^didFinishMappingBlock)(RKMappingResult *, NSError *);
Expand Down Expand Up @@ -189,6 +190,7 @@ - (instancetype)initWithRequest:(NSURLRequest *)request
self.responseDescriptors = responseDescriptors;
self.matchingResponseDescriptors = [self buildMatchingResponseDescriptors];
self.responseMappingsDictionary = [self buildResponseMappingsDictionary];
self.responseMappingArgumentsDictionary = [self buildResponseMappingArgumentsDictionary];
self.treatsEmptyResponseAsSuccess = YES;
self.mappingMetadata = @{}; // Initialize the metadata
}
Expand Down Expand Up @@ -237,6 +239,30 @@ - (NSDictionary *)buildResponseMappingsDictionary
return dictionary;
}

- (NSDictionary *)buildResponseMappingArgumentsDictionary
{
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (RKResponseDescriptor *responseDescriptor in self.matchingResponseDescriptors) {

NSDictionary *arguments = [responseDescriptor parsedArgumentsFromResponse:self.response];
if (arguments)
{
// We don't add nil keypath at an [NSNull null] key, because that causes a crash later
// in RKDictionaryByMergingDictionaryWithDictionary
if (responseDescriptor.keyPath)
{
[dictionary setObject:arguments forKey:responseDescriptor.keyPath];
}
else
{
[dictionary addEntriesFromDictionary:arguments];
}
}
}

return dictionary;
}

- (RKMappingResult *)performMappingWithObject:(id)sourceObject error:(NSError **)error
{
@throw [NSException exceptionWithName:NSInternalInconsistencyException
Expand All @@ -260,6 +286,12 @@ - (void)setMappingMetadata:(NSDictionary *)mappingMetadata
NSDictionary *HTTPMetadata = @{ @"HTTP": @{ @"request": @{ @"URL": self.request.URL, @"method": self.request.HTTPMethod, @"headers": [self.request allHTTPHeaderFields] ?: @{} },
@"response": @{ @"URL": self.response.URL, @"headers": [self.response allHeaderFields] ?: @{} } } };
_mappingMetadata = RKDictionaryByMergingDictionaryWithDictionary(HTTPMetadata, mappingMetadata);

if (self.responseMappingArgumentsDictionary)
{
NSDictionary *argumentsMetadata = @{ @"network" : @{ @"arguments" : self.responseMappingArgumentsDictionary } };
_mappingMetadata = RKDictionaryByMergingDictionaryWithDictionary(argumentsMetadata, _mappingMetadata);
}
}

- (void)cancel
Expand Down
38 changes: 38 additions & 0 deletions Tests/Logic/Network/RKResponseMapperOperationTest.m
Expand Up @@ -518,6 +518,44 @@ - (void)testThatResponseMapperMakesResponseHeadersAvailableToMetadata
expect(testUser.name).to.equal(@"application/json");
}

- (void)testThatResponseMapperMakesResponseMappingArgumentsAvailableToMetadataWithNilKeyPath
{
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/users"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:responseURL];
[request setAllHTTPHeaderFields:@{ @"Content-Type": @"application/xml" }];
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
NSData *data = [@"{\"name\": \"Blake\"}" dataUsingEncoding:NSUTF8StringEncoding];

RKTestUser *testUser = [RKTestUser new];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[mapping addAttributeMappingsFromDictionary:@{ @"@metadata.network.arguments.version": @"name" }];

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/api/:version/users" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithRequest:request response:response data:data responseDescriptors:@[ responseDescriptor ]];
mapper.targetObject = testUser;
[mapper start];
expect(testUser.name).to.equal(@"v1");
}

- (void)testThatResponseMapperMakesResponseMappingArgumentsAvailableToMetadataWithNonNilKeyPath
{
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/users"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:responseURL];
[request setAllHTTPHeaderFields:@{ @"Content-Type": @"application/xml" }];
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
NSData *data = [@"{\"users\":{\"name\": \"Blake\"}}" dataUsingEncoding:NSUTF8StringEncoding];

RKTestUser *testUser = [RKTestUser new];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[mapping addAttributeMappingsFromDictionary:@{ @"@metadata.network.arguments.users.version": @"name" }];

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/api/:version/users" keyPath:@"users" statusCodes:[NSIndexSet indexSetWithIndex:200]];
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithRequest:request response:response data:data responseDescriptors:@[ responseDescriptor ]];
mapper.targetObject = testUser;
[mapper start];
expect(testUser.name).to.equal(@"v1");
}

- (void)testThatResponseMapperMergesExistingMetadata
{
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/users"];
Expand Down

0 comments on commit bfa35e6

Please sign in to comment.