|
|
Sample Programs from NeXSTEP 3.3
/* ResetRelationships.m created by cfeder on Thu 15-Dec-1994 */
#import "ResetRelationships.h"
#import "ValueForKey.h"
#import "RelationshipKeySetter.h"
@implementation EODatabaseChannel (setForeignKey)
- objectForPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity
// returns existing object instance if there is one, or a fault otherwise
{
EODatabaseContext *context = [self databaseContext];
id object = [context objectForPrimaryKey:key entity:entity];
if (!object) {
object = [EOFault objectFaultWithPrimaryKey:key
entity:entity databaseChannel:self zone:[self zone]];
}
return object;
}
- fetchObjectDescribedByQualifier:(EOQualifier *)qualifier
// raises if not to-one.
{
BOOL success, autoTransaction = NO;
EODatabaseContext *context = [self databaseContext];
NSZone *zone = [self zone];
id object;
if (![context transactionNestingLevel]) {
[context beginTransaction];
autoTransaction = YES;
}
success = [self selectObjectsDescribedByQualifier:qualifier
fetchOrder:nil];
object = [self fetchWithZone:zone];
if (!success || !object || [self fetchWithZone:zone]) {
[self cancelFetch];
[NSException raise:NSInternalInconsistencyException format:@"%s: error fetching object", sel_getName(_cmd)];
}
if (autoTransaction) [context commitTransaction];
return object;
}
- destinationObjectForRelationship:relationship sourceObject:sourceObject
// look up an exising fault, or create a new one
{
id object;
// EODatabase *database = [[self databaseContext] database];
if ([relationship isToMany]) {
// EOF doesn't unique faults, so we just have to construct a new one
EOQualifier *qual = [EOQualifier qualifierForObject:sourceObject relationship:relationship];
object = [EOFault arrayFaultWithQualifier:qual
fetchOrder:nil databaseChannel:self zone:[self zone]];
} else {
// see if this is already in the uniquing table
if ([relationship isFlattened]) {
EOQualifier *qual = [EOQualifier qualifierForObject:sourceObject relationship:relationship];
// should fetch object from channel with qualifier
object = [self fetchObjectDescribedByQualifier:qual];
} else {
// for to-ones, the primary key is always the destination of the
// relationship
NSDictionary *pk = [relationship destinationValuesFromSourceObject:sourceObject];
object = [self objectForPrimaryKey:pk entity:[relationship destinationEntity]];
}
}
return object;
}
- (void)updateRelationshipsInObject:object forModifiedAttributes:(NSArray *)attributes
// After the values in object corresponding to the EOAttributes
// in the "attributes" array have been update (perhaps with
// takeValuesFromDictionary) this method can be called to update any
// corresponding relationship properties. So, if a foreign dept_id
// attribute way modified in a employee object, this would attempt to
// reset the "toDepartment" property to point at the corresponding
// department object.
{
// We should apply some caching here to make this fast. I.e. map directly
// from attribute to list of class property relationships that this participates in.
// For now we'll just be simple and slow.
NSMutableArray *affectedRelationships = [NSMutableArray array];
EOModel *model = [[[[self databaseContext] database] adaptor] model];
EOEntity *entity = [model entityForObject:object];
NSArray *classProperties = [entity classProperties];
NSArray *relationships = [entity relationships];
int i,count = [relationships count];
for(i=0; i<count; i++) {
EORelationship *relationship = [relationships objectAtIndex:i];
if ([classProperties indexOfObjectIdenticalTo:relationship] != NSNotFound) {
NSArray *joins = [relationship joins];
int j, jcount = [joins count];
for (j = 0; j < jcount; j++) {
EOJoin *join = [joins objectAtIndex:j];
if ([attributes indexOfObjectIdenticalTo:[join sourceAttribute]] != NSNotFound) {
[affectedRelationships addObject:relationship];
break;
}
}
}
}
// We now have a list of affected relationships that we need to retarget
{
count = [affectedRelationships count];
for(i=0; i<count; i++) {
EORelationship *relationship = [relationships objectAtIndex:i];
id dest = [self destinationObjectForRelationship:relationship sourceObject:object];
[object takeValue:dest forKey:[relationship name]];
}
}
}
@end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.