Skip to content

Instantly share code, notes, and snippets.

@chadpod
Created March 17, 2011 01:40
Show Gist options
  • Select an option

  • Save chadpod/873705 to your computer and use it in GitHub Desktop.

Select an option

Save chadpod/873705 to your computer and use it in GitHub Desktop.

Revisions

  1. chadpod created this gist Mar 17, 2011.
    261 changes: 261 additions & 0 deletions HRObject.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,261 @@
    //
    // HRObject.m
    //
    // Created by Chad Podoski on 11/23/09.
    // Copyright 2009 Shacked Software. All rights reserved.
    //

    #import "HRObject.h"

    #import "AppDelegate_Shared.h"

    @interface HRObject (Private)

    + (void)populateObject:(id)object withDictionary:(NSDictionary *)dict;
    + (id)managedObjectForEntity:(NSString *)entity uuid:(NSString *)uuid;

    @end


    @implementation HRObject

    + (void)initialize {
    [self setDelegate:self];
    [self setBaseURL:[NSURL URLWithString:SSBaseApiUrl]];
    [self setFormat:HRDataFormatJSON];

    //NSDictionary *params = [NSDictionary dictionaryWithObject:@"1234567" forKey:@"api_key"];
    //[self setDefaultParams:params];
    }

    /**
    * Called when the resource was succeffully fetched and encoded
    *
    * @param connection The connection object for the current request
    * @param resource The converted objc representation of the response data returned by the server.
    * @param object Any custom object you passed in while making the request.
    */
    + (void)restConnection:(NSURLConnection *)connection didReturnResource:(id)resource object:(id)object {

    /* Converts from the HTTPRiot model class to Core Data Model class and CRUD in managed object context */
    NSMutableSet *responseSet = [self convertToCoreData:resource];

    if (!IsEmpty(object) && [object respondsToSelector:@selector(httpRiotResponseReceived:)]) {
    [object performSelector:@selector(httpRiotResponseReceived:) withObject:responseSet];
    }
    }

    /**
    * Called when the connection receieves any type of response
    *
    * @param connection The connection object for the current request
    * @param response The response object returned by the server.
    * @param object Any custom object you passed in while making the request.
    */
    + (void)restConnection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response object:(id)object {
    NSLog(@"RESPONSE STATUS WAS:%i", [response statusCode]);
    }

    /**
    * Called when the connection fails in situations where the server is not available, etc.
    *
    * @param connection The connection object for the current request
    * @param error The error returned by the connection.
    * @param object Any custom object you passed in while making the request.
    */
    + (void)restConnection:(NSURLConnection *)connection didFailWithError:(NSError *)error object:(id)object {
    AlertWithMessage([error localizedDescription]);
    }

    /**
    * Called when the connection receieves a statusCode that isn't a success code.
    *
    * @param connection The connection object for the current request
    * @param error The error returned by the connection.
    * @param response The response object returned by the server.
    * @param object Any custom object you passed in while making the request.
    */
    + (void)restConnection:(NSURLConnection *)connection didReceiveError:(NSError *)error response:(NSHTTPURLResponse *)response object:(id)object {
    AlertWithMessage([error localizedDescription]);
    }

    /**
    * Called when the HRFormatter recieved an error parsing the response data.
    *
    * @param connection The connection object for the current request
    * @param error The parser error returned by the formatter.
    * @param body A string representation of the response body returned by the server.
    * @param object Any custom object you passed in while making the request.
    */
    + (void)restConnection:(NSURLConnection *)connection didReceiveParseError:(NSError *)error responseBody:(NSString *)body object:(id)object {
    AlertWithMessage([error localizedDescription]);
    }


    #pragma mark - Core Data Methods
    + (NSMutableSet *)convertToCoreData:(id)resource {

    NSMutableSet *result;

    /* Determine if we are dealing with a single object or an array of objects */
    if ([resource isKindOfClass:[NSDictionary class]]) {

    NSDictionary *dict = (NSDictionary *)resource;
    NSString *entity = [dict valueForKey:SSEntityKey];
    NSString *uuid = [dict valueForKey:SSUuidKey];

    /* Make sure object an entity name and an uuid */
    if (!IsEmpty(entity) && !IsEmpty(uuid)) {

    result = [NSMutableSet setWithCapacity:1];

    /* Class name needs to be prefixed with class prefix for this project */
    id object = [self managedObjectForEntity:entity uuid:uuid];

    // NSLog(@"******************************");
    // NSLog(@"BEFORE %@", object);
    [self populateObject:object withDictionary:resource];
    // NSLog(@"------------------------------");
    // NSLog(@"AFTER %@", object);

    [result addObject:object];
    }

    }else if ([resource isKindOfClass:[NSArray class]]) {

    result = [NSMutableSet setWithCapacity:[(NSArray *)resource count]];

    for (id object in resource) {
    [result unionSet:[self convertToCoreData:object]];
    }
    }

    return result;
    }

    + (void)populateObject:(id)object withDictionary:(NSDictionary *)dict {

    NSArray *keys = [dict allKeys];

    for (NSString *key in keys) {

    id value = [dict valueForKey:key];
    key = [key capitalizedString];
    key = [key stringByReplacingOccurrencesOfString:@"_" withString:@""];

    /* An NSArray value indicates that this is a relation */
    if ([value isKindOfClass:[NSArray class]]) {

    /* Recursive build the relation */
    NSMutableSet *relationSet = [self convertToCoreData:value];

    /* Add relation to object */
    SEL selector = NSSelectorFromString([NSString stringWithFormat:@"add%@:", key]);

    if ([object respondsToSelector:selector]) {
    [object performSelector:selector withObject:relationSet];
    }

    }

    /* A NSDictionary indicate a 1-to-1 relationship from Django Piston */
    else if ([value isKindOfClass:[NSDictionary class]]) {

    NSMutableSet *relationSet = [self convertToCoreData:value];

    if (!IsEmpty(relationSet) && [relationSet count] == 1) {

    /* Add object to model */
    SEL selector = NSSelectorFromString([NSString stringWithFormat:@"set%@:", key]);

    if ([object respondsToSelector:selector]) {
    [object performSelector:selector withObject:[relationSet anyObject]];
    }
    }
    }

    /* It is a simple attribute */
    else {

    SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@:", key]);

    if ([object respondsToSelector:setter]) {

    if (!IsEmpty(value) && ![value isEqual:[NSNull null]]) {

    if ([value isKindOfClass:[NSString class]]) {

    if (![value isEqualToString:@"<null>"]) {
    /* Just lowercase the first character */
    key = [key stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[key substringToIndex:1] lowercaseString]];

    SEL getter = NSSelectorFromString(key);

    if ([object respondsToSelector:getter]) {

    NSManagedObject *mObject = (NSManagedObject*)object;
    NSPropertyDescription *propDesc = [[[[mObject class] entityDescription]
    propertiesByName] objectForKey:key];



    if ([propDesc isMemberOfClass:[NSAttributeDescription class]]) {

    NSAttributeDescription *attribDesc = (NSAttributeDescription*)propDesc;

    if ([attribDesc attributeType] == NSDateAttributeType) {
    NSDate *date = [NSDate dateFromString:value];
    if (!IsEmpty(date)) {
    [object performSelector:setter withObject:date];
    }
    }
    else if ([attribDesc attributeType] == NSDecimalAttributeType) {
    NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:value];
    if (!IsEmpty(number)) {

    [object performSelector:setter withObject:number];
    }
    }
    else {
    [object performSelector:setter withObject:value];
    }
    }
    }
    }
    }
    else {
    [object performSelector:setter withObject:value];
    }
    }
    }
    }
    }
    }

    + (id)managedObjectForEntity:(NSString *)entity uuid:(NSString *)uuid {

    id object;

    NSManagedObjectContext *moc = [(AppDelegate_Shared*)[[UIApplication sharedApplication] delegate] managedObjectContext];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    [request setEntity:[NSEntityDescription entityForName:entity inManagedObjectContext:moc]];
    [request setPredicate:[NSPredicate predicateWithFormat:@"uuid = %@", uuid]];

    NSError *error = nil;
    NSArray *results = [moc executeFetchRequest:request error:&error];

    if (error) {
    NSLog(@"%@", error);
    }
    else if (!IsEmpty(results)) {
    object = [results objectAtIndex:0];
    }
    else {
    object = [NSEntityDescription insertNewObjectForEntityForName:entity inManagedObjectContext:moc];;
    }

    return object;

    }

    @end