// // PNObject.m // Pods // // Created by Giuseppe Nucifora on 28/12/15. // // #import "PNObject.h" #import #import #import @interface PNObject() @property (nonatomic, strong) NSDictionary *JSON; @property (nonatomic, strong) NSString *endPoint; @end @implementation PNObject - (instancetype) init { self = [super init]; if (self) { } return self; } - (instancetype) initWithJSON:(NSDictionary*) JSON { self = [self init]; if (self) { NSAssert(_objectMapping, @"You must create objectMapping"); _JSON = [[NSDictionary alloc] initWithDictionary:JSON]; [self populateObjectFromJSON:JSON]; } return self; } - (BOOL)isStringNull:(NSString *)str { if(nil == str || NSNull.null == (id)str) return YES; else return NO; } - (BOOL)isObjNull:(id)obj { if(nil == obj || NSNull.null == obj) return YES; else return NO; } - (NSDictionary *)reverseMapping { NSMutableDictionary *JSON = [NSMutableDictionary dictionary]; NSString *mappedJSONKey; NSString *mappedJSONType; NSDictionary *properties = [PNObjectProperty propertiesForClass:self.class]; for (NSString* propertyName in _objectMapping) { id mappingValue = [_objectMapping objectForKey:propertyName]; if([mappingValue isKindOfClass:NSDictionary.class]) { mappedJSONKey = [mappingValue valueForKey:@"key"]; mappedJSONType = [mappingValue valueForKey:@"type"]; } else { mappedJSONKey = mappingValue; } NSString *propertyType = [properties valueForKey:propertyName]; id value = [self valueForKey:propertyName]; // NSDate if([propertyType isEqualToString:@"NSDate"]) { value = [NSDate stringFromDate:value]; } // NSURL else if([propertyType isEqualToString:@"NSURL"]) { NSURL *url = value; value = [url absoluteString]; } // NSArray, NSMutableArray else if([propertyType isEqualToString:@"NSArray"] || [propertyType isEqualToString:@"NSMutableArray"]) { NSMutableArray *arr = [NSMutableArray array]; for(id LLObject in value) { SEL selector = NSSelectorFromString(@"reverseMapping"); NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [[PNObject class] instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:LLObject]; [invocation invoke]; NSDictionary *returnValue; [invocation getReturnValue:&returnValue]; [arr addObject:returnValue]; } value = arr; } // Other LLModel or an unidentified value else { BOOL isPNObjectSubclass = [NSClassFromString(propertyType) isSubclassOfClass:[PNObject class]]; if(isPNObjectSubclass) { SEL selector = NSSelectorFromString(@"reverseMapping"); NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [[PNObject class] instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:value]; [invocation invoke]; NSDictionary *returnValue; [invocation getReturnValue:&returnValue]; value = returnValue; } else { // do nothing } } [JSON setValue:value forKey:propertyName]; } _JSON = JSON; return _JSON; } - (void)populateObjectFromJSON:(id)JSON { NSDictionary *properties = [PNObjectProperty propertiesForClass:self.class]; for(NSString *propertyName in properties) { if([propertyName isEqualToString:@"mappingError"]) continue; NSString *mappedJSONKey; NSString *mappedJSONType; NSString *propertyType = [properties valueForKey:propertyName]; id mappingValue = [_objectMapping valueForKey:propertyName]; if([mappingValue isKindOfClass:NSDictionary.class]) { mappedJSONKey = [mappingValue valueForKey:@"key"]; mappedJSONType = [mappingValue valueForKey:@"type"]; } else { mappedJSONKey = mappingValue; } // Check if there is mapping for the property if([self isStringNull:mappedJSONKey]) { // No mapping so just continue continue; } // Get JSON value for the mapped key id value = [JSON valueForKeyPath:mappedJSONKey]; if([self isObjNull:value]) { continue; } //NSLog(@"Looking for : %@ -- %@ -- %@", propertyType, mappedJSONKey, value); ((void (^)())@{ @"c" : ^{ char val = [value charValue]; [self setValue:@(val) forKey:propertyName]; }, @"d" : ^{ double val = [value doubleValue]; [self setValue:@(val) forKey:propertyName]; }, @"f" : ^{ float val = [value floatValue]; [self setValue:@(val) forKey:propertyName]; }, @"i" : ^{ int val = [value intValue]; [self setValue:@(val) forKey:propertyName]; }, @"l" : ^{ long val = [value longValue]; [self setValue:@(val) forKey:propertyName]; }, @"s" : ^{ short val = [value shortValue]; [self setValue:@(val) forKey:propertyName]; }, @"NSString" : ^{ NSString *val = [NSString stringWithFormat:@"%@", value]; [self setValue:val forKey:propertyName]; }, @"NSNumber" : ^{ NSInteger val = [value integerValue]; [self setValue:@(val) forKey:propertyName]; }, @"NSDate" : ^{ NSString *str = [NSString stringWithFormat:@"%@", value]; NSDate *val = [NSDate dateFromString:str]; [self setValue:val forKey:propertyName]; }, @"NSArray" : ^{ NSMutableArray *arr = [NSMutableArray array]; for(id JSONObject in value) { PNObject *val = [[NSClassFromString(mappedJSONType) alloc] initWithJSON:JSONObject]; [arr addObject:val]; } [self setValue:arr forKey:propertyName]; }, @"NSMutableArray" : ^{ NSMutableArray *arr = [NSMutableArray array]; for(id JSONObject in value) { PNObject *val = [[NSClassFromString(mappedJSONType) alloc] initWithJSON:JSONObject]; [arr addObject:val]; } [self setValue:arr forKey:propertyName]; } }[propertyType] ?: ^{ BOOL isPNObjectSubclass = [NSClassFromString(propertyType) isSubclassOfClass:[PNObject class]]; if(isPNObjectSubclass) { PNObject *val = [[NSClassFromString(propertyType) alloc] initWithJSON:value]; [self setValue:val forKey:propertyName]; } else { NSString *errorStr = [NSString stringWithFormat:@"Property '%@' could not be assigned any value.", propertyName]; NSLog(@"%@",errorStr); } })(); } } #pragma mark PNObjectSubclassing + (NSString *) objectClassName { } + (NSDictionary *) objcetMapping { } #pragma mark - @end