diff --git a/OCMapper.xcodeproj/project.xcworkspace/xcuserdata/aryaxt.xcuserdatad/UserInterfaceState.xcuserstate b/OCMapper.xcodeproj/project.xcworkspace/xcuserdata/aryaxt.xcuserdatad/UserInterfaceState.xcuserstate
index 1d5324c..ea522c1 100644
Binary files a/OCMapper.xcodeproj/project.xcworkspace/xcuserdata/aryaxt.xcuserdatad/UserInterfaceState.xcuserstate and b/OCMapper.xcodeproj/project.xcworkspace/xcuserdata/aryaxt.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/BC3A5B12-DE29-448A-856D-62B5380399B4.plist b/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/BC3A5B12-DE29-448A-856D-62B5380399B4.plist
new file mode 100644
index 0000000..9a8cf0c
--- /dev/null
+++ b/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/BC3A5B12-DE29-448A-856D-62B5380399B4.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ classNames
+
+ ObjectMapperTests
+
+ testPerformance
+
+ com.apple.XCTPerformanceMetric_WallClockTime
+
+ baselineAverage
+ 0.01
+ baselineIntegrationDisplayName
+ Local Baseline
+
+
+
+
+
+
diff --git a/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/Info.plist b/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/Info.plist
index d06cb08..fdc0b96 100644
--- a/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/Info.plist
+++ b/OCMapper.xcodeproj/xcshareddata/xcbaselines/15B554CB171B7B3C0058E159.xcbaseline/Info.plist
@@ -35,6 +35,37 @@
com.apple.platform.iphonesimulator
+ BC3A5B12-DE29-448A-856D-62B5380399B4
+
+ localComputer
+
+ busSpeedInMHz
+ 100
+ cpuCount
+ 1
+ cpuKind
+ Intel Core i7
+ cpuSpeedInMHz
+ 2200
+ logicalCPUCoresPerPackage
+ 8
+ modelCode
+ MacBookPro11,2
+ physicalCPUCoresPerPackage
+ 4
+ platformIdentifier
+ com.apple.platform.macosx
+
+ targetArchitecture
+ x86_64
+ targetDevice
+
+ modelCode
+ iPhone7,2
+ platformIdentifier
+ com.apple.platform.iphonesimulator
+
+
diff --git a/OCMapper/Sample/Service Layer/OCMapperConfig.m b/OCMapper/Sample/Service Layer/OCMapperConfig.m
index bbe35f1..3abc769 100644
--- a/OCMapper/Sample/Service Layer/OCMapperConfig.m
+++ b/OCMapper/Sample/Service Layer/OCMapperConfig.m
@@ -18,11 +18,9 @@ @implementation OCMapperConfig
+ (void)configure
{
- ObjectInstanceProvider *instanceProvider = [[ObjectInstanceProvider alloc] init];
InCodeMappingProvider *inCodeMappingProvider = [[InCodeMappingProvider alloc] init];
CommonLoggingProvider *commonLoggingProvider = [[CommonLoggingProvider alloc] initWithLogLevel:LogLevelInfo];
- [[ObjectMapper sharedInstance] setInstanceProvider:instanceProvider];
[[ObjectMapper sharedInstance] setMappingProvider:inCodeMappingProvider];
[[ObjectMapper sharedInstance] setLoggingProvider:commonLoggingProvider];
diff --git a/OCMapper/Source/Instance Provider/InstanceProvider.h b/OCMapper/Source/Instance Provider/InstanceProvider.h
index 3abfa17..1b1ba8e 100644
--- a/OCMapper/Source/Instance Provider/InstanceProvider.h
+++ b/OCMapper/Source/Instance Provider/InstanceProvider.h
@@ -29,6 +29,7 @@
@protocol InstanceProvider
+- (BOOL)canHandleClass:(Class)class;
- (id)emptyInstanceForClass:(Class)class;
- (id)emptyCollectionInstance;
- (id)upsertObject:(NSObject *)object error:(NSError **)error;
diff --git a/OCMapper/Source/Instance Provider/ManagedObjectInstanceProvider.m b/OCMapper/Source/Instance Provider/ManagedObjectInstanceProvider.m
index fe6ea2a..b583647 100644
--- a/OCMapper/Source/Instance Provider/ManagedObjectInstanceProvider.m
+++ b/OCMapper/Source/Instance Provider/ManagedObjectInstanceProvider.m
@@ -63,6 +63,11 @@ - (id)init
#pragma mark - Public Methods -
+- (BOOL)canHandleClass:(Class)class
+{
+ return ([class isSubclassOfClass:NSManagedObject.class]) ? YES : NO;
+}
+
- (void)setUniqueKeys:(NSArray *)keys forClass:(Class)class withUpsertMode:(UpsertMode)upsertMode
{
for (id key in keys)
diff --git a/OCMapper/Source/Instance Provider/ObjectInstanceProvider.m b/OCMapper/Source/Instance Provider/ObjectInstanceProvider.m
index 6359327..38510e4 100644
--- a/OCMapper/Source/Instance Provider/ObjectInstanceProvider.m
+++ b/OCMapper/Source/Instance Provider/ObjectInstanceProvider.m
@@ -47,6 +47,16 @@ - (id)init
#pragma mark - InstanceProvider Methods -
+- (BOOL)canHandleClass:(Class)class
+{
+ static Class managedObjectClass = nil;
+
+ if (!managedObjectClass)
+ managedObjectClass = NSClassFromString(@"NSManagedObject");
+
+ return ([class isSubclassOfClass:managedObjectClass]) ? NO : YES;
+}
+
- (id)emptyInstanceForClass:(Class)class
{
return [[class alloc] init];
diff --git a/OCMapper/Source/ObjectMapper.h b/OCMapper/Source/ObjectMapper.h
index b9f42bc..98e355e 100644
--- a/OCMapper/Source/ObjectMapper.h
+++ b/OCMapper/Source/ObjectMapper.h
@@ -26,21 +26,19 @@
// THE SOFTWARE.
#import
-#import
-#import "ObjectMappingInfo.h"
-#import "InstanceProvider.h"
-#import "MappingProvider.h"
-#import "LoggingProvider.h"
+
+@protocol MappingProvider, LoggingProvider, InstanceProvider;
@interface ObjectMapper : NSObject
@property (nonatomic, strong) NSDateFormatter *defaultDateFormatter;
-@property (nonatomic, strong) id instanceProvider;
@property (nonatomic, strong) id mappingProvider;
@property (nonatomic, strong) id loggingProvider;
+@property (nonatomic, assign) BOOL normalizeDictionary;
+ (ObjectMapper *)sharedInstance;
- (id)objectFromSource:(id)source toInstanceOfClass:(Class)class;
- (id)dictionaryFromObject:(NSObject *)object;
+- (void)addInstanceProvider:(id )instanceProvider;
@end
diff --git a/OCMapper/Source/ObjectMapper.m b/OCMapper/Source/ObjectMapper.m
index acbe537..0a73c66 100644
--- a/OCMapper/Source/ObjectMapper.m
+++ b/OCMapper/Source/ObjectMapper.m
@@ -26,6 +26,12 @@
// THE SOFTWARE.
#import "ObjectMapper.h"
+#import
+#import "ObjectMappingInfo.h"
+#import "InstanceProvider.h"
+#import "MappingProvider.h"
+#import "LoggingProvider.h"
+#import "ObjectInstanceProvider.h"
#ifdef DEBUG
#define ILog(format, ...) [self.loggingProvider log:[NSString stringWithFormat:(format), ##__VA_ARGS__] withLevel:LogLevelInfo]
@@ -42,6 +48,7 @@ @interface ObjectMapper()
@property (nonatomic, strong) NSMutableArray *classNamesInMainBundle;
@property (nonatomic, strong) NSMutableDictionary *mappedClassNames;
@property (nonatomic, strong) NSMutableDictionary *mappedPropertyNames;
+@property (nonatomic, strong) NSMutableArray *instanceProviders;
@end
@implementation ObjectMapper
@@ -66,6 +73,10 @@ - (id)init
{
[self populateClassNamesFromMainBundle];
+ self.instanceProviders = [NSMutableArray array];
+ ObjectInstanceProvider *objectInstanceProvider = [[ObjectInstanceProvider alloc] init];
+ [self addInstanceProvider:objectInstanceProvider];
+
self.mappedClassNames = [NSMutableDictionary dictionary];
self.mappedPropertyNames = [NSMutableDictionary dictionary];
}
@@ -80,9 +91,6 @@ - (id)objectFromSource:(id)source toInstanceOfClass:(Class)class
if (!_mappingProvider)
@throw ([NSException exceptionWithName:@"MissingMappingProvider" reason:@"Mapping provider is not set" userInfo:nil]);
- if (!_instanceProvider)
- @throw ([NSException exceptionWithName:@"MissingInstanceProvider" reason:@"Instance provider is not set" userInfo:nil]);
-
if ([source isKindOfClass:[NSDictionary class]])
{
ILog(@"____________________ Mapping Dictionary to instance [%@] ____________________", NSStringFromClass(class));
@@ -112,6 +120,11 @@ - (id)dictionaryFromObject:(NSObject *)object
}
}
+- (void)addInstanceProvider:(id )instanceProvider
+{
+ [self.instanceProviders addObject:instanceProvider];
+}
+
#pragma mark - Private Methods -
- (void)populateClassNamesFromMainBundle
@@ -259,9 +272,10 @@ - (NSDictionary *)normalizedDictionaryFromDictionary:(NSDictionary *)source forC
- (id)processDictionary:(NSDictionary *)source forClass:(Class)class
{
- NSDictionary *normalizedSource = [self normalizedDictionaryFromDictionary:source forClass:class];
+ NSDictionary *normalizedSource = (self.normalizeDictionary) ? [self normalizedDictionaryFromDictionary:source forClass:class] : source;
- id object = [self.instanceProvider emptyInstanceForClass:class];
+ id instanceProvider = [self instanceProviderForClass:class];
+ id object = [instanceProvider emptyInstanceForClass:class];
for (NSString *key in normalizedSource)
{
@@ -276,13 +290,13 @@ - (id)processDictionary:(NSDictionary *)source forClass:(Class)class
if (mappingInfo)
{
- propertyName = [self.instanceProvider propertyNameForObject:object byCaseInsensitivePropertyName:mappingInfo.propertyKey];
+ propertyName = [instanceProvider propertyNameForObject:object byCaseInsensitivePropertyName:mappingInfo.propertyKey];
objectType = mappingInfo.objectType;
mappingTransformer = mappingInfo.transformer;
}
else
{
- propertyName = [self.instanceProvider propertyNameForObject:object byCaseInsensitivePropertyName:key];
+ propertyName = [instanceProvider propertyNameForObject:object byCaseInsensitivePropertyName:key];
if (propertyName && ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]))
{
@@ -350,7 +364,7 @@ - (id)processDictionary:(NSDictionary *)source forClass:(Class)class
}
NSError *error;
- object = [self.instanceProvider upsertObject:object error:&error];
+ object = [instanceProvider upsertObject:object error:&error];
if (error)
ELog(@"Attempt to update existing instance failed with error '%@' for class (%@) and object %@",
@@ -361,9 +375,21 @@ - (id)processDictionary:(NSDictionary *)source forClass:(Class)class
return object;
}
+- (id )instanceProviderForClass:(Class)class
+{
+ for (id instanceProvider in self.instanceProviders)
+ {
+ if ([instanceProvider canHandleClass:class])
+ return instanceProvider;
+ }
+
+ return nil;
+}
+
- (id)processArray:(NSArray *)value forClass:(Class)class
{
- id collection = [self.instanceProvider emptyCollectionInstance];
+ id instanceProvider = [self instanceProviderForClass:class];
+ id collection = [instanceProvider emptyCollectionInstance];
for (id objectInArray in value)
{
diff --git a/OCMapperTests/ManagedObjectMapperTest.m b/OCMapperTests/ManagedObjectMapperTest.m
index e4e32a7..ec931df 100644
--- a/OCMapperTests/ManagedObjectMapperTest.m
+++ b/OCMapperTests/ManagedObjectMapperTest.m
@@ -26,6 +26,7 @@
// THE SOFTWARE.
#import "ManagedObjectMapperTest.h"
+#import "User.h"
#import "CDUser.h"
#import "CDAddress.h"
#import "CDPost.h"
@@ -47,7 +48,7 @@ - (void)setUp
self.mapper = [[ObjectMapper alloc] init];
self.mapper.mappingProvider = self.mappingProvider;
- self.mapper.instanceProvider = self.instanceProvider;
+ [self.mapper addInstanceProvider:self.instanceProvider];
}
- (void)tearDown
@@ -404,4 +405,14 @@ - (void)testNumberOfCreatedManagedObjectsOnNonUpdateForUpsertModePurgeExisting
XCTAssertTrue(addresses.count == 2, @"Did Not update existing ManagedObject");
}
+- (void)testManagedObjectInstanceProviderShouldReturnFalseForNSObjectSubclasses
+{
+ XCTAssertFalse([self.instanceProvider canHandleClass:User.class]);
+}
+
+- (void)testManagedObjectInstanceProviderShouldReturnTrueForNSManagedObjectSubclasses
+{
+ XCTAssertTrue([self.instanceProvider canHandleClass:CDUser.class]);
+}
+
@end
diff --git a/OCMapperTests/ObjectMapperTests.m b/OCMapperTests/ObjectMapperTests.m
index a30b31d..d229dac 100644
--- a/OCMapperTests/ObjectMapperTests.m
+++ b/OCMapperTests/ObjectMapperTests.m
@@ -28,6 +28,7 @@
#import "ObjectMapperTests.h"
#import "ObjectMapper.h"
#import "User.h"
+#import "CDUser.h"
#import "Comment.h"
#import "SpecialUser.h"
@@ -47,7 +48,6 @@ - (void)setUp
self.mapper = [[ObjectMapper alloc] init];
self.mapper.mappingProvider = self.mappingProvider;
- self.mapper.instanceProvider = self.instanceProvider;
}
- (void)tearDown
@@ -361,6 +361,7 @@ - (void)testFlatDataToComplexObjectConversion
[self.mappingProvider mapFromDictionaryKey:@"city" toPropertyKey:@"address.city" forClass:[User class]];
[self.mappingProvider mapFromDictionaryKey:@"country" toPropertyKey:@"address.country" forClass:[User class]];
+ self.mapper.normalizeDictionary = YES;
User *user = [self.mapper objectFromSource:userDictionary toInstanceOfClass:[User class]];
XCTAssertTrue([[userDictionary objectForKey:@"firstName"] isEqual:user.firstName], @"Did not populate dictionary correctly");
@@ -415,7 +416,8 @@ - (void)testShouldPopulateDictionaryWithPropertyInSuperClass
XCTAssertTrue([user.power isEqual:[dictionary objectForKey:@"power"]], @"Did Not populate dictionary properly");
}
-- (void)testInverseMappingShouldMapKeysWithCorrectName {
+- (void)testInverseMappingShouldMapKeysWithCorrectName
+{
User *user = [[User alloc] init];
user.firstName = @"Aryan";
user.address = [[Address alloc] init];
@@ -435,14 +437,16 @@ - (void)testInverseMappingShouldMapKeysWithCorrectName {
XCTAssertTrue([[dictionary[@"location"] objectForKey:@"ct"] isEqualToString:user.address.city]);
}
-- (void)testShouldAutomaticallyGenerateInverseMapping {
+- (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 {
+- (void)testShouldNotAutomaticallyGenerateInverseMapping
+{
self.mappingProvider.automaticallyGenerateInverseMapping = NO;
[self.mappingProvider mapFromDictionaryKey:@"dateOfBirth" toPropertyKey:@"dob" forClass:[User class]];
ObjectMappingInfo *info = [self.mappingProvider mappingInfoForClass:[User class] andPropertyKey:@"dob"];
@@ -450,4 +454,14 @@ - (void)testShouldNotAutomaticallyGenerateInverseMapping {
XCTAssertNil(info);
}
+- (void)testObjectInstanceProviderShouldReturnTrueForNSObjectSubclasses
+{
+ XCTAssertTrue([self.instanceProvider canHandleClass:User.class]);
+}
+
+- (void)testObjectInstanceProviderShouldReturnFalseForNSManagedObjectSubclasses
+{
+ XCTAssertFalse([self.instanceProvider canHandleClass:CDUser.class]);
+}
+
@end