|
|
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.