Created
August 23, 2012 17:13
-
-
Save happyrobots/3438867 to your computer and use it in GitHub Desktop.
Mini Mapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Usage: | |
1. Initialize | |
MiniMapper *m = [MiniMapper new]; | |
2. Map | |
[m forClass:[MyClass class] mapAttributes:^(NSMutableDictionary *dict) { | |
[dict setObject:@"my_attribute" | |
forKey:@"my_property"]; | |
}]; | |
// Only one degree relationship | |
[m forClass:[MyClass class] mapHasOneRelationship:^(NSMutableDictionary *dict) { | |
[dict setObject:[NSArray arrayWithObjects:@"my_attribute", [MyChildClass class], nil] | |
forKey:@"my_property"]; | |
}]; | |
// Only one degree relationship | |
[m forClass:[MyClass class] mapHasManyRelationship:^(NSMutableDictionary *dict) { | |
[dict setObject:[NSArray arrayWithObjects:@"my_attribute", [MyChildrenClass class], nil] | |
forKey:@"my_property"]; | |
}]; | |
3. Create object from attributes (with or without relationships) | |
// without relationships | |
id instance = [m createPlainInstanceOf:[MyClass class] | |
fromSource:[NSDictionary dictionaryWithObjectsAndKeys: | |
@"My Value", @"my_attribute", | |
nil]]; | |
// with relationships | |
id instance = [m createInstanceOf:[MyClass class] | |
fromSource:[NSDictionary dictionaryWithObjectsAndKeys: | |
@"My Value", @"my_attribute", | |
nil]]; | |
4. Extract attributes from object (nested attributes are not supported yet) | |
NSDictionary *attrs = [m attributesOf:myClassInstance]; | |
*/ | |
/// MiniMapper.h | |
@interface MiniMapper : NSObject | |
- (void)forClass:(Class)klass | |
mapAttributes:(void (^)(NSMutableDictionary *dict))blk; | |
- (void)forClass:(Class)klass mapHasOneRelationship:(void (^)(NSMutableDictionary *dict))blk; | |
- (void)forClass:(Class)klass mapHasManyRelationship:(void (^)(NSMutableDictionary *dict))blk; | |
- (id)createPlainInstanceOf:(Class)klass | |
fromSource:(NSDictionary *)dict; | |
- (id)createInstanceOf:(Class)klass | |
fromSource:(NSDictionary *)dict; | |
- (NSDictionary *)attributesOf:(id)obj; | |
@end | |
/// MiniMapper.m | |
#import "MiniMapper.h" | |
@interface MiniMapper () | |
@property (nonatomic, retain) NSMutableDictionary *attributesMap; | |
@property (nonatomic, retain) NSMutableDictionary *hasOneRelationshipsMap; | |
@property (nonatomic, retain) NSMutableDictionary *hasManyRelationshipsMap; | |
@end | |
@implementation MiniMapper | |
@synthesize attributesMap; | |
@synthesize hasOneRelationshipsMap; | |
@synthesize hasManyRelationshipsMap; | |
- (id)init { | |
self = [super init]; | |
if (self) { | |
self.attributesMap = [NSMutableDictionary dictionary]; | |
self.hasOneRelationshipsMap = [NSMutableDictionary dictionary]; | |
self.hasManyRelationshipsMap = [NSMutableDictionary dictionary]; | |
} | |
return self; | |
} | |
- (void)dealloc { | |
self.attributesMap = nil; | |
self.hasOneRelationshipsMap = nil; | |
self.hasManyRelationshipsMap = nil; | |
[super dealloc]; | |
} | |
- (void)forClass:(Class)klass | |
mapAttributes:(void (^)(NSMutableDictionary *dict))blk { | |
[self forClass:klass map:blk usingMapping:self.attributesMap]; | |
} | |
- (void)forClass:(Class)klass mapHasOneRelationship:(void (^)(NSMutableDictionary *dict))blk { | |
[self forClass:klass map:blk usingMapping:self.hasOneRelationshipsMap]; | |
} | |
- (void)forClass:(Class)klass mapHasManyRelationship:(void (^)(NSMutableDictionary *dict))blk { | |
[self forClass:klass map:blk usingMapping:self.hasManyRelationshipsMap]; | |
} | |
- (void)forClass:(Class)klass | |
map:(void (^)(NSMutableDictionary *dict))blk | |
usingMapping:(NSMutableDictionary *)mapping { | |
NSMutableDictionary *map = [NSMutableDictionary dictionary]; | |
if (blk) { | |
blk(map); | |
} | |
map = [NSMutableDictionary dictionaryWithObjectsAndKeys:map, klass, nil]; | |
[mapping addEntriesFromDictionary:map]; | |
} | |
- (id)createPlainInstanceOf:(Class)klass | |
fromSource:(NSDictionary *)dict { | |
NSDictionary *classMap = [self.attributesMap objectForKey:klass]; | |
if (!classMap) return nil; | |
id result = [[klass alloc] init]; | |
for (id property in classMap) { | |
id attribute = [classMap objectForKey:property]; | |
[result setValue:[dict objectForKey:attribute] forKey:property]; | |
} | |
return [result autorelease]; | |
} | |
- (id)createInstanceOf:(Class)klass | |
fromSource:(NSDictionary *)dict { | |
id result = [self createPlainInstanceOf:klass fromSource:dict]; | |
NSDictionary *hasOneClassMap = [self.hasOneRelationshipsMap objectForKey:klass]; | |
for (id parentRelProperty in hasOneClassMap) { | |
NSArray *pair = [hasOneClassMap objectForKey:parentRelProperty]; | |
NSString *relAttr = [pair objectAtIndex:0]; | |
Class relClass = [pair lastObject]; | |
NSDictionary *relDict = [dict objectForKey:relAttr]; | |
id relObj = [self createPlainInstanceOf:relClass fromSource:relDict]; | |
[result setValue:relObj forKey:relAttr]; | |
} | |
NSDictionary *hasManyClassMap = [self.hasManyRelationshipsMap objectForKey:klass]; | |
for (id parentRelProperty in hasManyClassMap) { | |
NSArray *pair = [hasManyClassMap objectForKey:parentRelProperty]; | |
NSString *relAttr = [pair objectAtIndex:0]; | |
Class relClass = [pair lastObject]; | |
NSArray *relObjs = [dict objectForKey:relAttr]; | |
NSMutableArray *relList = [NSMutableArray array]; | |
for (NSDictionary *relDict in relObjs) { | |
id relObj = [self createPlainInstanceOf:relClass fromSource:relDict]; | |
if (relObj) [relList addObject:relObj]; | |
} | |
[result setValue:relList forKey:relAttr]; | |
} | |
return result; | |
} | |
- (NSDictionary *)attributesOf:(id)obj { | |
NSDictionary *map = [attributesMap objectForKey:[obj class]]; | |
if (!map) return [NSDictionary dictionary]; | |
NSMutableDictionary *dict = [NSMutableDictionary dictionary]; | |
for (NSString *property in map) { | |
NSString *attr = [map valueForKey:property]; | |
[dict setObject:[obj valueForKey:property] forKey:attr]; | |
} | |
return dict; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment