mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-24 04:46:01 +08:00
Added support for parser class specification by regular expression. closes #489
This commit is contained in:
committed by
Blake Watters
parent
53bbeca099
commit
99a108096f
@@ -22,39 +22,76 @@
|
||||
#import "RKParser.h"
|
||||
|
||||
/**
|
||||
The Parser Registry provides for the registration of RKParser classes
|
||||
for a particular MIME Type. This enables
|
||||
*/
|
||||
RKParserRegistry provides for the registration of RKParser classes
|
||||
that handle parsing/serializing for content by MIME Type. Registration
|
||||
is configured via exact string matches (i.e. application/json) or via regular
|
||||
expression.
|
||||
*/
|
||||
@interface RKParserRegistry : NSObject {
|
||||
NSMutableDictionary *_MIMETypeToParserClasses;
|
||||
NSMutableArray *_MIMETypeToParserClassesRegularExpressions;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the global shared singleton registry for MIME Type to Parsers
|
||||
|
||||
@return The global shared RKParserRegistry instance.
|
||||
*/
|
||||
+ (RKParserRegistry *)sharedRegistry;
|
||||
|
||||
/**
|
||||
Sets the global shared registry singleton to a new instance of RKParserRegistry
|
||||
|
||||
@param registry A new parser registry object to configure as the shared instance.
|
||||
*/
|
||||
+ (void)setSharedRegistry:(RKParserRegistry *)registry;
|
||||
|
||||
/**
|
||||
Instantiate and return a Parser for the given MIME Type
|
||||
Returns an instance of the RKParser conformant class registered to handle content
|
||||
with the given MIME Type.
|
||||
|
||||
MIME Types are searched in the order in which they are registered and exact
|
||||
string matches are favored over regular expressions.
|
||||
|
||||
@param MIMEType The MIME Type of the content to be parsed/serialized.
|
||||
@return An instance of the RKParser conformant class registered to handle the given MIME Type.
|
||||
*/
|
||||
- (id<RKParser>)parserForMIMEType:(NSString *)MIMEType;
|
||||
|
||||
/**
|
||||
Return the class registered for handling parser/encoder operations
|
||||
for a given MIME Type
|
||||
Returns an instance of the RKParser conformant class registered to handle content
|
||||
with the given MIME Type.
|
||||
|
||||
MIME Types are searched in the order in which they are registered and exact
|
||||
string matches are favored over regular expressions.
|
||||
|
||||
@param MIMEType The MIME Type of the content to be parsed/serialized.
|
||||
@return The RKParser conformant class registered to handle the given MIME Type.
|
||||
*/
|
||||
- (Class<RKParser>)parserClassForMIMEType:(NSString *)MIMEType;
|
||||
|
||||
/**
|
||||
Registers an RKParser conformant class as the handler for the specified MIME Type
|
||||
Registers an RKParser conformant class as the handler for MIME Types exactly matching the
|
||||
specified MIME Type string.
|
||||
|
||||
@param parserClass The RKParser conformant class to instantiate when parsing/serializing MIME Types matching MIMETypeExpression.
|
||||
@param MIMEType A MIME Type string for which instances of parserClass should be used for parsing/serialization.
|
||||
*/
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMEType:(NSString *)MIMEType;
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
|
||||
/**
|
||||
Registers an RKParser conformant class as the handler for MIME Types matching the
|
||||
specified regular expression.
|
||||
|
||||
@param parserClass The RKParser conformant class to instantiate when parsing/serializing MIME Types matching MIMETypeExpression.
|
||||
@param MIMETypeRegex A regular expression that matches MIME Types that should be handled by instances of parserClass.
|
||||
*/
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMETypeRegularExpression:(NSRegularExpression *)MIMETypeRegex;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Automatically configure the registry via run-time reflection of the RKParser classes
|
||||
available that ship with RestKit. This happens automatically when the shared registry
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
#import "RKParserRegistry.h"
|
||||
|
||||
RKParserRegistry* gSharedRegistry;
|
||||
RKParserRegistry *gSharedRegistry;
|
||||
|
||||
@implementation RKParserRegistry
|
||||
|
||||
+ (RKParserRegistry*)sharedRegistry {
|
||||
+ (RKParserRegistry *)sharedRegistry {
|
||||
if (gSharedRegistry == nil) {
|
||||
gSharedRegistry = [RKParserRegistry new];
|
||||
[gSharedRegistry autoconfigure];
|
||||
@@ -33,7 +33,7 @@ RKParserRegistry* gSharedRegistry;
|
||||
return gSharedRegistry;
|
||||
}
|
||||
|
||||
+ (void)setSharedRegistry:(RKParserRegistry*)registry {
|
||||
+ (void)setSharedRegistry:(RKParserRegistry *)registry {
|
||||
[registry retain];
|
||||
[gSharedRegistry release];
|
||||
gSharedRegistry = registry;
|
||||
@@ -43,6 +43,7 @@ RKParserRegistry* gSharedRegistry;
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_MIMETypeToParserClasses = [[NSMutableDictionary alloc] init];
|
||||
_MIMETypeToParserClassesRegularExpressions = [[NSMutableArray alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -50,18 +51,42 @@ RKParserRegistry* gSharedRegistry;
|
||||
|
||||
- (void)dealloc {
|
||||
[_MIMETypeToParserClasses release];
|
||||
[_MIMETypeToParserClassesRegularExpressions release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (Class<RKParser>)parserClassForMIMEType:(NSString*)MIMEType {
|
||||
return [_MIMETypeToParserClasses objectForKey:MIMEType];
|
||||
- (Class<RKParser>)parserClassForMIMEType:(NSString *)MIMEType {
|
||||
id parserClass = [_MIMETypeToParserClasses objectForKey:MIMEType];
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
if (!parserClass)
|
||||
{
|
||||
for (NSArray *regexAndClass in _MIMETypeToParserClassesRegularExpressions) {
|
||||
NSRegularExpression *regex = [regexAndClass objectAtIndex:0];
|
||||
NSUInteger numberOfMatches = [regex numberOfMatchesInString:MIMEType options:0 range:NSMakeRange(0, [MIMEType length])];
|
||||
if (numberOfMatches) {
|
||||
parserClass = [regexAndClass objectAtIndex:1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return parserClass;
|
||||
}
|
||||
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMEType:(NSString*)MIMEType {
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMEType:(NSString *)MIMEType {
|
||||
[_MIMETypeToParserClasses setObject:parserClass forKey:MIMEType];
|
||||
}
|
||||
|
||||
- (id<RKParser>)parserForMIMEType:(NSString*)MIMEType {
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMETypeRegularExpression:(NSRegularExpression *)MIMETypeRegex {
|
||||
NSArray *expressionAndClass = [NSArray arrayWithObjects:MIMETypeRegex, parserClass, nil];
|
||||
[_MIMETypeToParserClassesRegularExpressions addObject:expressionAndClass];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (id<RKParser>)parserForMIMEType:(NSString *)MIMEType {
|
||||
Class parserClass = [self parserClassForMIMEType:MIMEType];
|
||||
if (parserClass) {
|
||||
return [[[parserClass alloc] init] autorelease];
|
||||
@@ -74,8 +99,8 @@ RKParserRegistry* gSharedRegistry;
|
||||
Class parserClass = nil;
|
||||
|
||||
// JSON
|
||||
NSSet* JSONParserClassNames = [NSSet setWithObjects:@"RKJSONParserJSONKit", @"RKJSONParserYAJL", @"RKJSONParserSBJSON", @"RKJSONParserNXJSON", nil];
|
||||
for (NSString* parserClassName in JSONParserClassNames) {
|
||||
NSSet *JSONParserClassNames = [NSSet setWithObjects:@"RKJSONParserJSONKit", @"RKJSONParserYAJL", @"RKJSONParserSBJSON", @"RKJSONParserNXJSON", nil];
|
||||
for (NSString *parserClassName in JSONParserClassNames) {
|
||||
parserClass = NSClassFromString(parserClassName);
|
||||
if (parserClass) {
|
||||
[self setParserClass:parserClass forMIMEType:RKMIMETypeJSON];
|
||||
|
||||
@@ -53,4 +53,36 @@
|
||||
assertThat(parser, is(instanceOf([RKXMLParserXMLReader class])));
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfExactStringMatchForMIMEType {
|
||||
RKParserRegistry* registry = [[RKParserRegistry new] autorelease];
|
||||
[registry setParserClass:[RKJSONParserJSONKit class] forMIMEType:RKMIMETypeJSON];
|
||||
id<RKParser> parser = [registry parserForMIMEType:RKMIMETypeJSON];
|
||||
assertThat(parser, is(instanceOf([RKJSONParserJSONKit class])));
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfRegularExpressionMatchForMIMEType {
|
||||
RKParserRegistry *registry = [[RKParserRegistry new] autorelease];
|
||||
NSError *error = nil;
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"application/xml\\+\\w+" options:0 error:&error];
|
||||
[registry setParserClass:[RKJSONParserJSONKit class] forMIMETypeRegularExpression:regex];
|
||||
id<RKParser> parser = [registry parserForMIMEType:@"application/xml+whatever"];
|
||||
assertThat(parser, is(instanceOf([RKJSONParserJSONKit class])));
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfExactStringMatchIsFavoredOverRegularExpression {
|
||||
RKParserRegistry *registry = [[RKParserRegistry new] autorelease];
|
||||
NSError *error = nil;
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"application/xml\\+\\w+" options:0 error:&error];
|
||||
[registry setParserClass:[RKJSONParserJSONKit class] forMIMETypeRegularExpression:regex];
|
||||
[registry setParserClass:[RKXMLParserXMLReader class] forMIMEType:@"application/xml+whatever"];
|
||||
|
||||
// Exact match
|
||||
id<RKParser> exactParser = [registry parserForMIMEType:@"application/xml+whatever"];
|
||||
assertThat(exactParser, is(instanceOf([RKXMLParserXMLReader class])));
|
||||
|
||||
// Fallback to regex
|
||||
id<RKParser> regexParser = [registry parserForMIMEType:@"application/xml+different"];
|
||||
assertThat(regexParser, is(instanceOf([RKJSONParserJSONKit class])));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user