Skip to content

Commit

Permalink
Refactor deserialization to support format config
Browse files Browse the repository at this point in the history
Add a remoteSiteFormat property to CoreManager to enable setting the format in the app delegate in the same way as remoteSiteURL.  This patch also lays the foundation for other deserializers by removing a hardcoded reference to JSON in CoreResource, although it falls back to JSON if no format is specified.
  • Loading branch information
isaac committed Jul 26, 2010
1 parent 9948473 commit c8ca496
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 39 deletions.
57 changes: 25 additions & 32 deletions CoreDeserializer.m
Expand Up @@ -29,38 +29,31 @@ - (id) initWithSource:(id)sourceObj andResourceClass:(Class)clazz {


- (void) main {
// Use format to change deserialization class and convert serialized string into resources
Class newClass = [resourceClass performSelector:@selector(deserializerClassForFormat:) withObject:[self format]];
if (newClass != nil) {

// Get Core Manager from resource class if it hasn't been defined yet
if (coreManager == nil)
coreManager = [[resourceClass performSelector:@selector(coreManager)] retain];

// Create "scratchpad" object context; we will merge this context into the main context once deserialization is complete
managedObjectContext = [[coreManager newContext] retain];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:managedObjectContext];

resources = [[self resourcesFromString:[self sourceString]] retain];

// Attempt to save object context; if there's an error, it will be placed in the CoreResult (which is sent to the target)
[managedObjectContext save:&error];

[self performSelectorOnMainThread:@selector(notify) withObject:nil waitUntilDone:NO];

// Remove context save observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification object:managedObjectContext];

return;
}

// Log error if level is high enough
if (error != nil && coreManager.logLevel > 3)
NSLog(@"CoreDeserializer error: %@", [error description]);
// Get Core Manager from resource class if it hasn't been defined yet
if (coreManager == nil)
coreManager = [[resourceClass performSelector:@selector(coreManager)] retain];

// Create "scratchpad" object context; we will merge this context into the main context once deserialization is complete
managedObjectContext = [[coreManager newContext] retain];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:managedObjectContext];

resources = [[self resourcesFromString:[self sourceString]] retain];

// Attempt to save object context; if there's an error, it will be placed in the CoreResult (which is sent to the target)
[managedObjectContext save:&error];

[self performSelectorOnMainThread:@selector(notify) withObject:nil waitUntilDone:NO];

// Remove context save observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification object:managedObjectContext];

// Log error if level is high enough
if (error != nil && coreManager.logLevel > 3)
NSLog(@"CoreDeserializer error: %@", [error description]);
}


Expand Down
2 changes: 2 additions & 0 deletions CoreManager.h
Expand Up @@ -17,6 +17,7 @@
NSOperationQueue *deserialzationQueue;

NSString *remoteSiteURL;
NSString *remoteSiteFormat;

// Default setting for whether or not to get data from within the bundle (instead of performing remote HTTP requests)
BOOL useBundleRequests;
Expand All @@ -42,6 +43,7 @@
@property (nonatomic, retain) NSOperationQueue *deserialzationQueue;

@property (nonatomic, retain) NSString *remoteSiteURL;
@property (nonatomic, retain) NSString *remoteSiteFormat;
@property (nonatomic, assign) BOOL useBundleRequests;
@property (nonatomic, assign) float bundleRequestDelay;

Expand Down
6 changes: 5 additions & 1 deletion CoreManager.m
Expand Up @@ -16,7 +16,7 @@ @implementation CoreManager

@synthesize persistentStoreCoordinator, managedObjectContext, managedObjectModel;
@synthesize requestQueue, deserialzationQueue;
@synthesize remoteSiteURL, useBundleRequests, bundleRequestDelay, defaultDateParser;
@synthesize remoteSiteURL, remoteSiteFormat, useBundleRequests, bundleRequestDelay, defaultDateParser;
@synthesize entityDescriptions, modelProperties, modelRelationships, modelAttributes;
@synthesize logLevel;

Expand Down Expand Up @@ -54,6 +54,9 @@ - (id) initWithOptions:(NSDictionary*)options {

logLevel = 1;

if (remoteSiteFormat == nil)
remoteSiteFormat = @"json";

// ===== Core Data initialization ===== //

// Create primary managed object model
Expand Down Expand Up @@ -170,6 +173,7 @@ - (void)dealloc {
[modelRelationships release];

[remoteSiteURL release];
[remoteSiteFormat release];

[managedObjectContext release];
[managedObjectModel release];
Expand Down
3 changes: 2 additions & 1 deletion CoreResource.h
Expand Up @@ -31,6 +31,7 @@ typedef enum _Action {
+ (BOOL) useBundleRequests;

+ (NSString*) remoteSiteURL;
+ (NSString*) remoteSiteFormat;
+ (NSString*) remoteCollectionName;
+ (NSString*) remoteURLForCollectionAction:(Action)action;
+ (NSString*) remoteURLForResource:(id)resourceId action:(Action)action;
Expand All @@ -55,7 +56,7 @@ typedef enum _Action {
+ (NSDateFormatter*) dateParser;
+ (NSDateFormatter*) dateParserForField:(NSString*)field;

+ (Class) deserializerClassForFormat:(NSString*)format;
+ (Class) deserializerClass;
//+ (id) resourceCollectionFromJSONCollection:(id)jsonCollection withParent:(id)parent;
//+ (id) resourcePropertiesFromJSONElement:(id)jsonElement withParent:(id)parent;

Expand Down
14 changes: 9 additions & 5 deletions CoreResource.m
Expand Up @@ -32,6 +32,10 @@ + (NSString*) remoteSiteURL {
return [[self coreManager] remoteSiteURL];
}

+ (NSString*) remoteSiteFormat {
return [[self coreManager] remoteSiteFormat];
}

+ (NSString*) remoteCollectionName {
return [[[NSStringFromClass(self) deCamelizeWith:@"_"] substringFromIndex:1] stringByAppendingString:@"s"];
}
Expand Down Expand Up @@ -103,8 +107,8 @@ + (NSDateFormatter*) dateParserForField:(NSString*)field {
return [self dateParser];
}

+ (Class) deserializerClassForFormat:(NSString*)format {
return NSClassFromString($S(@"Core%@Deserializer", [format uppercaseString]));
+ (Class) deserializerClass {
return NSClassFromString($S(@"Core%@Deserializer", [[self remoteSiteFormat] uppercaseString]));
}

/**
Expand Down Expand Up @@ -603,7 +607,7 @@ + (void) findRemote:(id)resourceId {

+ (void) findRemote:(id)resourceId andNotify:(id)del withSelector:(SEL)selector {
CoreRequest *request = [[[CoreRequest alloc] initWithURL:
[CoreUtils URLWithSite:[self remoteURLForResource:resourceId action:Read] andFormat:@"json" andParameters:nil]] autorelease];
[CoreUtils URLWithSite:[self remoteURLForResource:resourceId action:Read] andFormat:[self remoteSiteFormat] andParameters:nil]] autorelease];
request.delegate = self;
request.didFinishSelector = @selector(findRemoteDidFinish:);
request.didFailSelector = @selector(findRemoteDidFail:);
Expand Down Expand Up @@ -632,7 +636,7 @@ + (void) findAllRemote:(id)parameters {

+ (void) findAllRemote:(id)parameters andNotify:(id)del withSelector:(SEL)selector {
CoreRequest *request = [[[CoreRequest alloc] initWithURL:
[CoreUtils URLWithSite:[self remoteURLForCollectionAction:Read] andFormat:@"json" andParameters:parameters]] autorelease];
[CoreUtils URLWithSite:[self remoteURLForCollectionAction:Read] andFormat:[self remoteSiteFormat] andParameters:parameters]] autorelease];
request.delegate = self;
request.didFinishSelector = @selector(findRemoteDidFinish:);
request.didFailSelector = @selector(findRemoteDidFail:);
Expand All @@ -653,7 +657,7 @@ + (void) findAllRemote:(id)parameters andNotify:(id)del withSelector:(SEL)select

+ (void) findRemoteDidFinish:(CoreRequest*)request {
// Create and enqueue deserializer in non-blocking thread
CoreDeserializer* deserializer = [[CoreJSONDeserializer alloc] initWithSource:request andResourceClass:self];
CoreDeserializer* deserializer = [[[self deserializerClass] alloc] initWithSource:request andResourceClass:self];
deserializer.target = request.coreDelegate;
deserializer.action = request.coreSelector;
[[[self coreManager] deserialzationQueue] addOperation:deserializer];
Expand Down

0 comments on commit c8ca496

Please sign in to comment.