Skip to content

Instantly share code, notes, and snippets.

@happyrobots
Created August 23, 2012 17:13
Show Gist options
  • Save happyrobots/3438867 to your computer and use it in GitHub Desktop.
Save happyrobots/3438867 to your computer and use it in GitHub Desktop.
Mini Mapper
/*
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