|
|
1.1 ! root 1: /* ResetRelationships.m created by cfeder on Thu 15-Dec-1994 */ ! 2: ! 3: #import "ResetRelationships.h" ! 4: #import "ValueForKey.h" ! 5: #import "RelationshipKeySetter.h" ! 6: ! 7: @implementation EODatabaseChannel (setForeignKey) ! 8: - objectForPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity ! 9: // returns existing object instance if there is one, or a fault otherwise ! 10: { ! 11: EODatabaseContext *context = [self databaseContext]; ! 12: id object = [context objectForPrimaryKey:key entity:entity]; ! 13: if (!object) { ! 14: object = [EOFault objectFaultWithPrimaryKey:key ! 15: entity:entity databaseChannel:self zone:[self zone]]; ! 16: } ! 17: return object; ! 18: } ! 19: ! 20: - fetchObjectDescribedByQualifier:(EOQualifier *)qualifier ! 21: // raises if not to-one. ! 22: { ! 23: BOOL success, autoTransaction = NO; ! 24: EODatabaseContext *context = [self databaseContext]; ! 25: NSZone *zone = [self zone]; ! 26: id object; ! 27: ! 28: if (![context transactionNestingLevel]) { ! 29: [context beginTransaction]; ! 30: autoTransaction = YES; ! 31: } ! 32: ! 33: success = [self selectObjectsDescribedByQualifier:qualifier ! 34: fetchOrder:nil]; ! 35: object = [self fetchWithZone:zone]; ! 36: if (!success || !object || [self fetchWithZone:zone]) { ! 37: [self cancelFetch]; ! 38: [NSException raise:NSInternalInconsistencyException format:@"%s: error fetching object", sel_getName(_cmd)]; ! 39: } ! 40: ! 41: if (autoTransaction) [context commitTransaction]; ! 42: return object; ! 43: } ! 44: ! 45: - destinationObjectForRelationship:relationship sourceObject:sourceObject ! 46: // look up an exising fault, or create a new one ! 47: { ! 48: id object; ! 49: // EODatabase *database = [[self databaseContext] database]; ! 50: ! 51: if ([relationship isToMany]) { ! 52: // EOF doesn't unique faults, so we just have to construct a new one ! 53: EOQualifier *qual = [EOQualifier qualifierForObject:sourceObject relationship:relationship]; ! 54: object = [EOFault arrayFaultWithQualifier:qual ! 55: fetchOrder:nil databaseChannel:self zone:[self zone]]; ! 56: } else { ! 57: // see if this is already in the uniquing table ! 58: if ([relationship isFlattened]) { ! 59: EOQualifier *qual = [EOQualifier qualifierForObject:sourceObject relationship:relationship]; ! 60: ! 61: // should fetch object from channel with qualifier ! 62: object = [self fetchObjectDescribedByQualifier:qual]; ! 63: } else { ! 64: // for to-ones, the primary key is always the destination of the ! 65: // relationship ! 66: NSDictionary *pk = [relationship destinationValuesFromSourceObject:sourceObject]; ! 67: object = [self objectForPrimaryKey:pk entity:[relationship destinationEntity]]; ! 68: } ! 69: } ! 70: return object; ! 71: } ! 72: ! 73: - (void)updateRelationshipsInObject:object forModifiedAttributes:(NSArray *)attributes ! 74: // After the values in object corresponding to the EOAttributes ! 75: // in the "attributes" array have been update (perhaps with ! 76: // takeValuesFromDictionary) this method can be called to update any ! 77: // corresponding relationship properties. So, if a foreign dept_id ! 78: // attribute way modified in a employee object, this would attempt to ! 79: // reset the "toDepartment" property to point at the corresponding ! 80: // department object. ! 81: { ! 82: // We should apply some caching here to make this fast. I.e. map directly ! 83: // from attribute to list of class property relationships that this participates in. ! 84: // For now we'll just be simple and slow. ! 85: NSMutableArray *affectedRelationships = [NSMutableArray array]; ! 86: EOModel *model = [[[[self databaseContext] database] adaptor] model]; ! 87: EOEntity *entity = [model entityForObject:object]; ! 88: NSArray *classProperties = [entity classProperties]; ! 89: NSArray *relationships = [entity relationships]; ! 90: int i,count = [relationships count]; ! 91: ! 92: for(i=0; i<count; i++) { ! 93: EORelationship *relationship = [relationships objectAtIndex:i]; ! 94: ! 95: if ([classProperties indexOfObjectIdenticalTo:relationship] != NSNotFound) { ! 96: NSArray *joins = [relationship joins]; ! 97: int j, jcount = [joins count]; ! 98: ! 99: for (j = 0; j < jcount; j++) { ! 100: EOJoin *join = [joins objectAtIndex:j]; ! 101: if ([attributes indexOfObjectIdenticalTo:[join sourceAttribute]] != NSNotFound) { ! 102: [affectedRelationships addObject:relationship]; ! 103: break; ! 104: } ! 105: } ! 106: } ! 107: } ! 108: ! 109: // We now have a list of affected relationships that we need to retarget ! 110: { ! 111: count = [affectedRelationships count]; ! 112: for(i=0; i<count; i++) { ! 113: EORelationship *relationship = [relationships objectAtIndex:i]; ! 114: id dest = [self destinationObjectForRelationship:relationship sourceObject:object]; ! 115: [object takeValue:dest forKey:[relationship name]]; ! 116: } ! 117: } ! 118: } ! 119: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.