|
|
1.1 ! root 1: /* RelationshipKeySetter.m created by cfeder on Tue 08-Nov-1994 */ ! 2: ! 3: #import "RelationshipKeySetter.h" ! 4: #import "ValueForKey.h" ! 5: #import <objc/objc-runtime.h> ! 6: ! 7: @implementation EOEntity (attrsNamed) ! 8: - attributesNamed:(NSArray *)names ! 9: { ! 10: int i, count = [names count]; ! 11: NSMutableArray *result = [NSMutableArray arrayWithCapacity:count]; ! 12: for(i=0; i<count; i++) { ! 13: EOAttribute *attr = [self attributeNamed:[names objectAtIndex:i]]; ! 14: if (attr) ! 15: [result addObject:attr]; ! 16: } ! 17: return result; ! 18: } ! 19: ! 20: - createObject ! 21: { ! 22: id eo = nil; ! 23: const char *className = [self className]; ! 24: Class eoClass = objc_lookUpClass (className); ! 25: ! 26: if (!eoClass) eoClass = [EOGenericRecord class]; ! 27: ! 28: if (eoClass) { ! 29: eo = [eoClass allocWithZone:[self zone]]; ! 30: if ([eo respondsToSelector:@selector(initWithPrimaryKey:entity:)]) ! 31: eo = [eo initWithPrimaryKey:nil entity:self]; ! 32: else ! 33: [eo init]; ! 34: } ! 35: return [eo autorelease]; ! 36: } ! 37: @end ! 38: ! 39: ! 40: @implementation EORelationship (setPropsInDestObject) ! 41: - (NSArray *)sourceKeys ! 42: { ! 43: EORelationship *sourceRelationship = [self isFlattened] ! 44: ? [[self componentRelationships] objectAtIndex:0] : self; ! 45: NSArray *joins = [sourceRelationship joins]; ! 46: int i, count = [joins count]; ! 47: NSMutableArray *results = [NSMutableArray arrayWithCapacity:count]; ! 48: ! 49: for (i = 0; i < count; i++) { ! 50: EOJoin *join = [joins objectAtIndex:i]; ! 51: [results addObject:[[join sourceAttribute] name]]; ! 52: } ! 53: return results; ! 54: } ! 55: ! 56: - (void)setJoinPropertiesInDestinationObject:destination fromSourceObject:source ! 57: { ! 58: NSArray *joins = [self joins]; ! 59: int i, count = [joins count]; ! 60: ! 61: for (i = 0; i < count; i++) { ! 62: EOJoin *join = [joins objectAtIndex:i]; ! 63: id val = [(NSObject *)source valueForKey:[[join sourceAttribute] name]]; ! 64: if (!val) val = [EONull null]; ! 65: [destination takeValue:val forKey:[[join destinationAttribute] name]]; ! 66: } ! 67: } ! 68: ! 69: - (void)setJoinPropertiesInSourceObject:source fromDestinationObject:destination ! 70: { ! 71: ! 72: NSArray *joins = [self joins]; ! 73: int i, count = [joins count]; ! 74: ! 75: for (i = 0; i < count; i++) { ! 76: EOJoin *join = [joins objectAtIndex:i]; ! 77: id val = [(NSObject*)destination valueForKey:[[join destinationAttribute] name]]; ! 78: if (!val) val = [EONull null]; ! 79: [source takeValue:val forKey:[[join sourceAttribute] name]]; ! 80: } ! 81: } ! 82: ! 83: - (NSDictionary *)destinationValuesFromSourceObject:sourceObject ! 84: { ! 85: NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; ! 86: [self setJoinPropertiesInDestinationObject:dictionary fromSourceObject:sourceObject]; ! 87: return dictionary; ! 88: } ! 89: ! 90: - (BOOL)hasJoinsOnPrimaryKeyOfSourceEntity ! 91: { ! 92: // FIX ME! ! 93: // this is not quite right for multi-attribute keys (the ordering may ! 94: // cause a false mismatch) ! 95: return [[self sourceKeys] isEqual:[[self entity] primaryKeyAttributeNames]]; ! 96: } ! 97: ! 98: - (void)updateMasterObject:master withNewDestinationObject:destination ! 99: // For to-one relationships! ! 100: { ! 101: // Decide which way to propagate the attributes based on which side of the ! 102: // relationship hooks to a primary key. ! 103: if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) ! 104: [self setJoinPropertiesInDestinationObject:destination fromSourceObject:master]; ! 105: else ! 106: [self setJoinPropertiesInSourceObject:destination fromDestinationObject:master]; ! 107: } ! 108: ! 109: - linkObjectForSourceObject:master destinationObject:destination ! 110: // created an intermediate object for many-to-many relationship through ! 111: // an intermediate table. Initializes keys of intermediate object using ! 112: // keys from source and destination object ! 113: { ! 114: NSArray *relationships = [self componentRelationships]; ! 115: EORelationship *sourceToLink = [relationships objectAtIndex:0]; ! 116: EORelationship *linkToDestination = [relationships objectAtIndex:1]; ! 117: EOEntity *linkEntity = [sourceToLink destinationEntity]; ! 118: id link = [linkEntity createObject]; ! 119: [sourceToLink setJoinPropertiesInDestinationObject:link fromSourceObject:master]; ! 120: [linkToDestination setJoinPropertiesInSourceObject:link fromDestinationObject:destination]; ! 121: return link; ! 122: } ! 123: ! 124: - updateKeysForSourceObject:source destinationObject:destination ! 125: // Sets keys on source or destination to maintain consistency for ! 126: // the source to now map to destination for this relationship. ! 127: // Does not actually assign destination to ivar in source (just messes ! 128: // with the keys). ! 129: // Returns the modified object (source or destination). In the case of ! 130: // a many to many returns a newly created link object. ! 131: // The caller is reposible for inserting or updating the returned ! 132: // object in the database. ! 133: { ! 134: id modifiedObject = nil; ! 135: ! 136: if ([self isToMany]) { ! 137: // figure out what values we need to snarf from our parents ! 138: if ([self isFlattened]) { ! 139: // Many to many create link obj Delete link none to-many ! 140: // I'm assuming there's only one link object... ! 141: modifiedObject = [self linkObjectForSourceObject:source destinationObject:destination]; ! 142: } else { ! 143: // PK -> FK D->FK := M->PK none none to-many ! 144: [self setJoinPropertiesInDestinationObject:destination fromSourceObject:source]; ! 145: modifiedObject = destination; ! 146: } ! 147: } else { ! 148: if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) { ! 149: // PK -> PK D->PK := M->PK None none to-one ! 150: [self setJoinPropertiesInDestinationObject:destination fromSourceObject:source]; ! 151: modifiedObject = destination; ! 152: } else { ! 153: // FK -> PK M->FK := D->PK M->FK=NULL none to-one ! 154: // We need to update the master with a new foreign key. ! 155: // send it to the dataSource as well... ! 156: [self setJoinPropertiesInSourceObject:source fromDestinationObject:destination]; ! 157: modifiedObject = source; ! 158: } ! 159: } ! 160: return modifiedObject; ! 161: } ! 162: ! 163: ! 164: - updateKeysForDeleteOfDestinationObject:destination fromSourceObject:source ! 165: // Sets keys on source or destination to maintain consistency for ! 166: // a delete of the destination from the source. Returns the object ! 167: // modified, or a synthesized link object that must be deleted to ! 168: // affect the delete. The caller is responsible for updating the ! 169: // source object, or deleting the destination or link in the database. ! 170: // ! 171: // This does not actually update destination to ivar in source (just messes ! 172: // with the keys). ! 173: { ! 174: id modifiedObject = nil; ! 175: ! 176: if ([self isToMany]) { ! 177: // figure out what values we need to snarf from our parents ! 178: if ([self isFlattened]) { ! 179: // Many to many create link obj Delete link to-many ! 180: // I'm assuming there's only one link object... ! 181: modifiedObject = [self linkObjectForSourceObject:source destinationObject:destination]; ! 182: } else { ! 183: // PK -> FK D->FK := M->PK Delete D to-many ! 184: // Nil out foreign key in destination ! 185: [self setJoinPropertiesInDestinationObject:destination fromSourceObject:nil]; ! 186: modifiedObject = destination; ! 187: } ! 188: } else { ! 189: if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) { ! 190: // PK -> PK D->PK := M->PK delete D to-one ! 191: // no use nilling out destinations primary key. Row must be deleted ! 192: modifiedObject = destination; ! 193: } else { ! 194: // FK -> PK M->FK := D->PK M->FK=NULL to-one ! 195: // nil out foreign key in source ! 196: [self setJoinPropertiesInSourceObject:source fromDestinationObject:nil]; ! 197: modifiedObject = source; ! 198: } ! 199: } ! 200: return modifiedObject; ! 201: } ! 202: ! 203: @end ! 204: ! 205:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.