diff --git a/OCMapper.xcodeproj/project.pbxproj b/OCMapper.xcodeproj/project.pbxproj index 53ff065..ff1c34d 100644 --- a/OCMapper.xcodeproj/project.pbxproj +++ b/OCMapper.xcodeproj/project.pbxproj @@ -27,7 +27,6 @@ 1502B3B117CDA75B00C095DE /* GoogleSearchResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1502B3B017CDA75B00C095DE /* GoogleSearchResult.m */; }; 1502B3B317CDADE300C095DE /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1502B3B217CDADE300C095DE /* Storyboard.storyboard */; }; 15371EC01727879700A508F4 /* ObjectMappingConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = 15371EBF1727879700A508F4 /* ObjectMappingConfig.plist */; }; - 15371EC517278C6300A508F4 /* PLISTMappingProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 15371EC417278C6300A508F4 /* PLISTMappingProvider.m */; }; 157B3076171E3655005AAB02 /* CoreDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 157B3075171E3655005AAB02 /* CoreDataManager.m */; }; 157B307C171E36D4005AAB02 /* CDUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 157B307B171E36D4005AAB02 /* CDUser.m */; }; 157B307F171E3714005AAB02 /* OCMapper.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 157B307D171E3714005AAB02 /* OCMapper.xcdatamodeld */; }; @@ -113,8 +112,6 @@ 1502B3B017CDA75B00C095DE /* GoogleSearchResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoogleSearchResult.m; sourceTree = ""; }; 1502B3B217CDADE300C095DE /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = ""; }; 15371EBF1727879700A508F4 /* ObjectMappingConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ObjectMappingConfig.plist; sourceTree = ""; }; - 15371EC317278C6300A508F4 /* PLISTMappingProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLISTMappingProvider.h; sourceTree = ""; }; - 15371EC417278C6300A508F4 /* PLISTMappingProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLISTMappingProvider.m; sourceTree = ""; }; 157B3074171E3655005AAB02 /* CoreDataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreDataManager.h; path = ../CoreDataManager.h; sourceTree = ""; }; 157B3075171E3655005AAB02 /* CoreDataManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CoreDataManager.m; path = ../CoreDataManager.m; sourceTree = ""; }; 157B3078171E3673005AAB02 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; @@ -261,15 +258,6 @@ path = Models; sourceTree = ""; }; - 15371EC217278C4500A508F4 /* PLIST Mapping */ = { - isa = PBXGroup; - children = ( - 15371EC317278C6300A508F4 /* PLISTMappingProvider.h */, - 15371EC417278C6300A508F4 /* PLISTMappingProvider.m */, - ); - path = "PLIST Mapping"; - sourceTree = ""; - }; 157B3084171E4518005AAB02 /* Core Data */ = { isa = PBXGroup; children = ( @@ -314,7 +302,6 @@ 157B315017237C75005AAB02 /* Mapping Provider */ = { isa = PBXGroup; children = ( - 15371EC217278C4500A508F4 /* PLIST Mapping */, 15EF052D172783F70041358D /* In Code Mapping */, 157B315217237C87005AAB02 /* MappingProvider.h */, 15E2B97B171BEAEB00526C77 /* ObjectMappingInfo.h */, @@ -581,7 +568,6 @@ 157B314417234ACB005AAB02 /* ObjectInstanceProvider.m in Sources */, 157B314717234ADF005AAB02 /* ManagedObjectInstanceProvider.m in Sources */, 15EF0535172783F70041358D /* InCodeMappingProvider.m in Sources */, - 15371EC517278C6300A508F4 /* PLISTMappingProvider.m in Sources */, 15A1933F1766CBB800016904 /* CommonLoggingProvider.m in Sources */, 1502B37117CD94EA00C095DE /* SampleViewController.m in Sources */, 1502B38A17CD985300C095DE /* AFHTTPClient.m in Sources */, diff --git a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h index 6179e6d..f911dd5 100644 --- a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h +++ b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h @@ -31,9 +31,79 @@ @interface InCodeMappingProvider : NSObject +/** + * Defaults to true, and if the value is true + * If true, for every dictionary-to-property mapping, it creates an inverse mapping + * So when a mapping is written to convert a dictionary key named "dob" to a property named "dateOfBirth" + * an inverse mapping is generated. Next time you convert that object to a dictionary, + * the dictionary key would be named "dob",which is mapped from a property named "dateOfBirth" + */ +@property (nonatomic, assign) BOOL automaticallyGenerateInverseMapping; + +/** + * Set key/property Mapping to be used for converting a dictionary to a model object + * + * @param dictionaryKey NSString key in the dictionary + * @param propertyKey NSString name of the property + * @param objectType Class to be instantiated and assigned to property + * @param class Class to be assign mapping to + */ - (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString *)propertyKey withObjectType:(Class)objectType forClass:(Class)class; + +/** + * Set key/property Mapping to be used for converting a dictionary to a model object + * + * @param dictionaryKey NSString key in the dictionary + * @param propertyKey NSString name of the property + * @param class Class to be assign mapping to + * @param transformer Block to be used for transforming an item in dictionary into a desired result and assign to property + */ - (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString *)propertyKey forClass:(Class)class withTransformer:(MappingTransformer)transformer; + +/** + * Set key/property Mapping to be used for converting a dictionary to a model object + * + * @param dictionaryKey NSString key in the dictionary + * @param propertyKey NSString name of the property + * @param class Class to be assign mapping to + */ - (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString *)propertyKey forClass:(Class)class; -- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forProperty:(NSString *)property andClass:(Class)class; + +/** + * Set key/property Mapping to be used for converting a model object to dictionary + * + * @param dictionaryKey NSString key in the dictionary + * @param propertyKey NSString name of the property + * @param class Class to be assign mapping to + */ +- (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class; + +/** + * Set key/property Mapping to be used for converting a model object to dictionary + * + * @param dictionaryKey NSString key in the dictionary + * @param propertyKey NSString name of the property + * @param class Class to be assign mapping to + * @param transformer Block to be used for transforming an item in dictionary into a desired result and assign to property + */ +- (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class withTransformer:(MappingTransformer)transformer; + +/** + * Set dateformatter to be used for converting a dictionary to a model object + * + * @param dateFormatter NSDateFormatter a dateformatter + * @param propertyKey NSString name of the property + * @param class Class to be assign mapping to + */ +- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forPropertyKey:(NSString *)propertyKey andClass:(Class)class; + +/** + * Set dateformatter to be used for converting a model object to a dictionary + * + * @param dateFormatter NSDateFormatter a dateformatter + * @param propertyKey NSString name of the property + * @param class Class to be assign mapping to + */ +- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forDictionaryKey:(NSString *)dictionaryKey andClass:(Class)class; @end diff --git a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m index 222b677..5ff118b 100644 --- a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m +++ b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m @@ -31,7 +31,9 @@ @interface InCodeMappingProvider() @property (nonatomic, strong) NSMutableDictionary *mappingDictionary; +@property (nonatomic, strong) NSMutableDictionary *inverseMappingDictionary; @property (nonatomic, strong) NSMutableDictionary *dateFormatterDictionary; +@property (nonatomic, strong) NSMutableDictionary *inverseDateFormatterDictionary; @end @implementation InCodeMappingProvider @@ -44,8 +46,11 @@ - (id)init { if (self = [super init]) { + self.automaticallyGenerateInverseMapping = YES; self.mappingDictionary = [NSMutableDictionary dictionary]; + self.inverseMappingDictionary = [NSMutableDictionary dictionary]; self.dateFormatterDictionary = [NSMutableDictionary dictionary]; + self.inverseDateFormatterDictionary = [NSMutableDictionary dictionary]; } return self; @@ -58,6 +63,11 @@ - (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString * ObjectMappingInfo *info = [[ObjectMappingInfo alloc] initWithDictionaryKey:dictionaryKey propertyKey:propertyKey andObjectType:objectType]; NSString *key = [self uniqueKeyForClass:class andKey:dictionaryKey]; [self.mappingDictionary setObject:info forKey:key]; + + if (self.automaticallyGenerateInverseMapping) + { + [self mapFromPropertyKey:propertyKey toDictionaryKey:dictionaryKey forClass:class]; + } } - (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString *)propertyKey forClass:(Class)class @@ -72,10 +82,33 @@ - (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString * [self.mappingDictionary setObject:info forKey:key]; } -- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forProperty:(NSString *)property andClass:(Class)class +- (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class { + ObjectMappingInfo *info = [[ObjectMappingInfo alloc] initWithDictionaryKey:dictionaryKey propertyKey:propertyKey andObjectType:nil]; + NSString *key = [self uniqueKeyForClass:class andKey:propertyKey]; + [self.inverseMappingDictionary setObject:info forKey:key]; +} + +- (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class withTransformer:(MappingTransformer)transformer { + ObjectMappingInfo *info = [[ObjectMappingInfo alloc] initWithDictionaryKey:dictionaryKey propertyKey:propertyKey andTransformer:transformer]; + NSString *key = [self uniqueKeyForClass:class andKey:propertyKey]; + [self.inverseMappingDictionary setObject:info forKey:key]; +} + +- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forPropertyKey:(NSString *)property andClass:(Class)class { NSString *key = [self uniqueKeyForClass:class andKey:property]; [self.dateFormatterDictionary setObject:dateFormatter forKey:key]; + + if (self.automaticallyGenerateInverseMapping) + { + [self setDateFormatter:dateFormatter forDictionaryKey:property andClass:class]; + } +} + +- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forDictionaryKey:(NSString *)dictionaryKey andClass:(Class)class +{ + NSString *key = [self uniqueKeyForClass:class andKey:dictionaryKey]; + [self.inverseDateFormatterDictionary setObject:dateFormatter forKey:key]; } #pragma mark - public Methods - @@ -93,9 +126,20 @@ - (ObjectMappingInfo *)mappingInfoForClass:(Class)class andDictionaryKey:(NSStri return [self.mappingDictionary objectForKey:key]; } -- (NSDateFormatter *)dateFormatterForClass:(Class)class andProperty:(NSString *)property +- (ObjectMappingInfo *)mappingInfoForClass:(Class)class andPropertyKey:(NSString *)source { + NSString *key = [self uniqueKeyForClass:class andKey:source]; + return [self.inverseMappingDictionary objectForKey:key]; +} + +- (NSDateFormatter *)dateFormatterForClass:(Class)class andPropertyKey:(NSString *)propertyKey { - NSString *key = [self uniqueKeyForClass:class andKey:property]; + NSString *key = [self uniqueKeyForClass:class andKey:propertyKey]; + return [self.dateFormatterDictionary objectForKey:key]; +} + +- (NSDateFormatter *)dateFormatterForClass:(Class)class andDictionaryKey:(NSString *)dictionaryKey +{ + NSString *key = [self uniqueKeyForClass:class andKey:dictionaryKey]; return [self.dateFormatterDictionary objectForKey:key]; } diff --git a/OCMapper/Source/Mapping Provider/MappingProvider.h b/OCMapper/Source/Mapping Provider/MappingProvider.h index d66388a..880efd0 100644 --- a/OCMapper/Source/Mapping Provider/MappingProvider.h +++ b/OCMapper/Source/Mapping Provider/MappingProvider.h @@ -31,6 +31,8 @@ @protocol MappingProvider - (ObjectMappingInfo *)mappingInfoForClass:(Class)class andDictionaryKey:(NSString *)key; -- (NSDateFormatter *)dateFormatterForClass:(Class)class andProperty:(NSString *)property; +- (ObjectMappingInfo *)mappingInfoForClass:(Class)class andPropertyKey:(NSString *)key; +- (NSDateFormatter *)dateFormatterForClass:(Class)class andPropertyKey:(NSString *)key; +- (NSDateFormatter *)dateFormatterForClass:(Class)class andDictionaryKey:(NSString *)key; @end diff --git a/OCMapper/Source/Mapping Provider/PLIST Mapping/PLISTMappingProvider.h b/OCMapper/Source/Mapping Provider/PLIST Mapping/PLISTMappingProvider.h deleted file mode 100644 index 2341e1e..0000000 --- a/OCMapper/Source/Mapping Provider/PLIST Mapping/PLISTMappingProvider.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// PLISTMappingProvider.h -// OCMapper -// -// Created by Aryan Gh on 4/23/13. -// Copyright (c) 2013 Aryan Ghassemi. All rights reserved. -// -// https://github.com/aryaxt/OCMapper -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import -#import "MappingProvider.h" -#import "ObjectMappingInfo.h" - -@interface PLISTMappingProvider : NSObject - -- (id)initWithFileName:(NSString *)fileName; - -@end diff --git a/OCMapper/Source/Mapping Provider/PLIST Mapping/PLISTMappingProvider.m b/OCMapper/Source/Mapping Provider/PLIST Mapping/PLISTMappingProvider.m deleted file mode 100644 index 05d43f6..0000000 --- a/OCMapper/Source/Mapping Provider/PLIST Mapping/PLISTMappingProvider.m +++ /dev/null @@ -1,116 +0,0 @@ -// -// PLISTMappingProvider.m -// OCMapper -// -// Created by Aryan Gh on 4/23/13. -// Copyright (c) 2013 Aryan Ghassemi. All rights reserved. -// -// https://github.com/aryaxt/OCMapper -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import "PLISTMappingProvider.h" - -#define PROPERTY_KEY_KEY @"PropertyKey" -#define DICTIONARY_KEY_KEY @"DictionaryKey" -#define DATEFORMAT_KEY @"DateFormat" -#define TIME_ZONE_KEY @"TimeZone" -#define OBJECT_TYPE_KEY @"ObjectType" - -@interface PLISTMappingProvider() -@property (nonatomic, strong) NSMutableDictionary *mappingDictionary; -@property (nonatomic, strong) NSMutableDictionary *dateFormatterDictionary; -@end - -@implementation PLISTMappingProvider -@synthesize mappingDictionary; -@synthesize dateFormatterDictionary; - -- (id)initWithFileName:(NSString *)fileName -{ - if (self = [super init]) - { - self.mappingDictionary = [NSMutableDictionary dictionary]; - self.mappingDictionary = [NSMutableDictionary dictionary]; - - NSString* path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"]; - NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:path]; - [self populateMappingDictionaryFromDictionry:dictionary]; - } - - return self; -} - -#pragma mark - private Methods - - -- (void)populateMappingDictionaryFromDictionry:(NSDictionary *)dictionary -{ - for (NSString *classString in dictionary) - { - Class class = NSClassFromString(classString); - NSDictionary *classDictionary = [dictionary objectForKey:classString]; - - for (NSDictionary *dict in classDictionary) - { - NSString *propertyKey = [dict objectForKey:PROPERTY_KEY_KEY]; - NSString *dictionaryKey = [dict objectForKey:DICTIONARY_KEY_KEY]; - NSString *dateFormatString = [dict objectForKey:PROPERTY_KEY_KEY]; - NSString *timeZone = [dict objectForKey:PROPERTY_KEY_KEY]; - Class objectType = NSClassFromString([dict objectForKey:OBJECT_TYPE_KEY]); - NSDateFormatter *dateFormatter; - - if (dateFormatString.length > 0) - { - dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:dateFormatString]; - - if (timeZone.length > 0) - [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:timeZone]]; - - NSString *key = [self uniqueKeyForClass:class andKey:propertyKey]; - [self.dateFormatterDictionary setObject:dateFormatter forKey:key]; - } - - ObjectMappingInfo *mappingInfo = [[ObjectMappingInfo alloc] initWithDictionaryKey:dictionaryKey propertyKey:propertyKey andObjectType:objectType]; - - [self.mappingDictionary setObject:mappingInfo forKey:[self uniqueKeyForClass:class andKey:dictionaryKey]]; - } - } -} - -- (NSString *)uniqueKeyForClass:(Class)class andKey:(NSString *)key -{ - return [[NSString stringWithFormat:@"%@-%@", NSStringFromClass(class), key] lowercaseString]; -} - -#pragma mark - MappingProvider Methods - - -- (ObjectMappingInfo *)mappingInfoForClass:(Class)class andDictionaryKey:(NSString *)source -{ - NSString *key = [self uniqueKeyForClass:class andKey:source]; - return [self.mappingDictionary objectForKey:key]; -} - -- (NSDateFormatter *)dateFormatterForClass:(Class)class andProperty:(NSString *)property -{ - NSString *key = [self uniqueKeyForClass:class andKey:property]; - return [self.dateFormatterDictionary objectForKey:key]; -} - -@end diff --git a/OCMapper/Source/ObjectMapper.m b/OCMapper/Source/ObjectMapper.m index 0e5b963..acbe537 100644 --- a/OCMapper/Source/ObjectMapper.m +++ b/OCMapper/Source/ObjectMapper.m @@ -170,12 +170,19 @@ - (NSDictionary *)processDictionaryFromObject:(NSObject *)object for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; - NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)]; - Class class = NSClassFromString([self typeForProperty:propertyName andClass:[object class]]); - id propertyValue = [object valueForKey:(NSString *)propertyName]; + NSString *originalPropertyName = [NSString stringWithUTF8String:property_getName(property)]; + Class class = NSClassFromString([self typeForProperty:originalPropertyName andClass:[object class]]); + id propertyValue = [object valueForKey:(NSString *)originalPropertyName]; + + ObjectMappingInfo *mapingInfo = [self.mappingProvider mappingInfoForClass:[object class] andPropertyKey:originalPropertyName]; + NSString *propertyName = (mapingInfo) ? mapingInfo.dictionaryKey : originalPropertyName; + if (mapingInfo.transformer) { + propertyValue = mapingInfo.transformer(propertyValue, object); + [props setObject:propertyValue forKey:propertyName]; + } // If class is in the main bundle it's an application specific class - if ([NSBundle mainBundle] == [NSBundle bundleForClass:[propertyValue class]]) + else if ([NSBundle mainBundle] == [NSBundle bundleForClass:[propertyValue class]]) { if (propertyValue) [props setObject:[self dictionaryFromObject:propertyValue] forKey:propertyName]; } @@ -184,7 +191,12 @@ - (NSDictionary *)processDictionaryFromObject:(NSObject *)object { if (class == [NSDate class]) { - if (self.defaultDateFormatter) + NSDateFormatter *dateFormatter = [self.mappingProvider dateFormatterForClass:[object class] andDictionaryKey:originalPropertyName]; + + if (!dateFormatter) + dateFormatter = self.defaultDateFormatter; + + if (dateFormatter) { propertyValue = [self.defaultDateFormatter stringFromDate:propertyValue]; } @@ -197,8 +209,7 @@ - (NSDictionary *)processDictionaryFromObject:(NSObject *)object { propertyValue = [self processDictionaryFromArray:propertyValue]; } - - + if (propertyValue) [props setObject:propertyValue forKey:propertyName]; } } @@ -427,7 +438,7 @@ - (Class)classFromString:(NSString *)className - (NSDate *)dateFromString:(NSString *)string forProperty:(NSString *)property andClass:(Class)class { NSDate *date; - NSDateFormatter *customDateFormatter = [self.mappingProvider dateFormatterForClass:class andProperty:property]; + NSDateFormatter *customDateFormatter = [self.mappingProvider dateFormatterForClass:class andPropertyKey:property]; if (customDateFormatter) { diff --git a/OCMapper/Source/ObjectMappingInfo.h b/OCMapper/Source/ObjectMappingInfo.h index 029f5cc..48e9191 100644 --- a/OCMapper/Source/ObjectMappingInfo.h +++ b/OCMapper/Source/ObjectMappingInfo.h @@ -27,6 +27,15 @@ #import +/** + * Definition of a block that is called when a data transformer is set. + * This block is used for both converting dictionary to model object and reverse + * + * @param currentNode Current node to be converted + * @param parentNode Parent Node + * + * @return id + */ typedef id (^MappingTransformer)(id currentNode, id parentNode); @interface ObjectMappingInfo : NSObject diff --git a/OCMapperTests/ObjectMapperTests.h b/OCMapperTests/ObjectMapperTests.h index 7dcf12e..7aa0357 100644 --- a/OCMapperTests/ObjectMapperTests.h +++ b/OCMapperTests/ObjectMapperTests.h @@ -29,7 +29,6 @@ #import "ObjectMapper.h" #import "InCodeMappingProvider.h" #import "ObjectInstanceProvider.h" -#import "PLISTMappingProvider.h" #import "CommonLoggingProvider.h" @interface ObjectMapperTests : XCTestCase diff --git a/OCMapperTests/ObjectMapperTests.m b/OCMapperTests/ObjectMapperTests.m index 5a637e4..a30b31d 100644 --- a/OCMapperTests/ObjectMapperTests.m +++ b/OCMapperTests/ObjectMapperTests.m @@ -196,8 +196,8 @@ - (void)testCustomDateConversion [userDict setObject:dateOfBirthString forKey:@"dateOfBirth"]; [userDict setObject:accountCreationDateString forKey:@"accountCreationDate"]; - [self.mappingProvider setDateFormatter:dateOfBirthFormatter forProperty:@"dateOfBirth" andClass:[User class]]; - [self.mappingProvider setDateFormatter:accountCreationFormatter forProperty:@"accountCreationDate" andClass:[User class]]; + [self.mappingProvider setDateFormatter:dateOfBirthFormatter forPropertyKey:@"dateOfBirth" andClass:[User class]]; + [self.mappingProvider setDateFormatter:accountCreationFormatter forPropertyKey:@"accountCreationDate" andClass:[User class]]; User *user = [self.mapper objectFromSource:userDict toInstanceOfClass:[User class]]; XCTAssertNotNil(user.accountCreationDate, @"Did nor populate date"); @@ -352,12 +352,6 @@ - (void)testMappingshouldNotBeCaseSensitiveForDictionaryKeyValue XCTAssertEqualObjects(user.firstName, firstName, @"firstName did not populate correctly"); } -- (void)testPlistMapping -{ - PLISTMappingProvider *provider = [[PLISTMappingProvider alloc] initWithFileName:@"ObjectMappingConfig"]; - self.mapper.mappingProvider = provider; -} - - (void)testFlatDataToComplexObjectConversion { NSMutableDictionary *userDictionary = [NSMutableDictionary dictionary]; @@ -392,17 +386,6 @@ - (void)testShouldMapPropertyInSuperClass XCTAssertTrue([[[userDictionary objectForKey:@"address"] objectForKey:@"city"] isEqual:user.address.city], @"Did not populate dictionary correctly"); } -- (void)testShouldPopulateDictionaryWithPropertyInSuperClass -{ - SpecialUser *user = [[SpecialUser alloc] init]; - user.power = @"stealth"; - user.firstName = @"Aryan"; - - NSDictionary *dictionary = [self.mapper dictionaryFromObject:user]; - XCTAssertTrue([user.firstName isEqual:[dictionary objectForKey:@"firstName"]], @"Did Not populate dictionary properly"); - XCTAssertTrue([user.power isEqual:[dictionary objectForKey:@"power"]], @"Did Not populate dictionary properly"); -} - - (void)testShouldTransformDataCorrectly { NSMutableDictionary *userDictionary = [NSMutableDictionary dictionary]; [userDictionary setObject:@"Aryan" forKey:@"firstName"]; @@ -421,4 +404,50 @@ - (void)testShouldTransformDataCorrectly { XCTAssertTrue([user.address.city isEqualToString:@"San Diego"]); } +- (void)testShouldPopulateDictionaryWithPropertyInSuperClass +{ + SpecialUser *user = [[SpecialUser alloc] init]; + user.power = @"stealth"; + user.firstName = @"Aryan"; + + NSDictionary *dictionary = [self.mapper dictionaryFromObject:user]; + XCTAssertTrue([user.firstName isEqual:[dictionary objectForKey:@"firstName"]], @"Did Not populate dictionary properly"); + XCTAssertTrue([user.power isEqual:[dictionary objectForKey:@"power"]], @"Did Not populate dictionary properly"); +} + +- (void)testInverseMappingShouldMapKeysWithCorrectName { + User *user = [[User alloc] init]; + user.firstName = @"Aryan"; + user.address = [[Address alloc] init]; + user.address.city = @"SF"; + + [self.mappingProvider mapFromPropertyKey:@"firstName" toDictionaryKey:@"fName" forClass:[User class]]; + [self.mappingProvider mapFromPropertyKey:@"address" toDictionaryKey:@"location" forClass:[User class]]; + [self.mappingProvider mapFromPropertyKey:@"city" toDictionaryKey:@"ct" forClass:[Address class]]; + [self.mappingProvider mapFromPropertyKey:@"dateOfBirth" toDictionaryKey:@"dob" forClass:[User class] withTransformer:^id(id currentNode, id parentNode) { + + return @"2014"; + }]; + + NSDictionary *dictionary = [self.mapper dictionaryFromObject:user]; + XCTAssertTrue([dictionary[@"fName"] isEqualToString:user.firstName]); + XCTAssertTrue([dictionary[@"dob"] isEqualToString:@"2014"]); + XCTAssertTrue([[dictionary[@"location"] objectForKey:@"ct"] isEqualToString:user.address.city]); +} + +- (void)testShouldAutomaticallyGenerateInverseMapping { + [self.mappingProvider mapFromDictionaryKey:@"dateOfBirth" toPropertyKey:@"dob" forClass:[User class]]; + ObjectMappingInfo *info = [self.mappingProvider mappingInfoForClass:[User class] andPropertyKey:@"dob"]; + + XCTAssertTrue([info.dictionaryKey isEqualToString:@"dateOfBirth"]); +} + +- (void)testShouldNotAutomaticallyGenerateInverseMapping { + self.mappingProvider.automaticallyGenerateInverseMapping = NO; + [self.mappingProvider mapFromDictionaryKey:@"dateOfBirth" toPropertyKey:@"dob" forClass:[User class]]; + ObjectMappingInfo *info = [self.mappingProvider mappingInfoForClass:[User class] andPropertyKey:@"dob"]; + + XCTAssertNil(info); +} + @end