libs-gdl2/EOAccess/EOUtilities.m
Dave Wetzel 4878a85bbe * EOAccess/EOSQLExpression.m
fix include for less warnings on mac
	* EOAccess/EOEntity.m
	fix include for less warnings on mac
	isPrimaryKeyValidInObject: 0 is NOT a valid PK value
	* EOAccess/EOAdaptor.m
	fix include for less warnings on mac
	isDroppedConnectionException
	add comment and remove logs
	* EOAccess/EOSQLQualifier.m
	* EOAccess/EODatabaseDataSource.m
	* EOAccess/EOAdaptorContext.m
	* EOAccess/EORelationship.m
	* EOAccess/EOUtilities.m
	* EOAccess/EOSchemaGeneration.m
	* EOAccess/EOAdaptorChannel.m
	* EOAccess/EODatabaseChannel.m	
	fix include for less warnings on mac
	* EOAccess/EODatabaseContext.h
	add support for shouldHandleDatabaseException (WO 4.5)
	* EOAccess/EODatabaseContext.m
	add support for shouldHandleDatabaseException
	add [newRow addEntriesFromDictionary:objectPK] 
	to merge PKValues into the values of the EO.
	without that it is impossible to work.
	relayPrimaryKey: object: entity:
	Hopefully fixed. 
	add _delegateHandledDatabaseException:
	fixed _primaryKeyForObject: raiseException:
	(we raise always for now)
	* EOAccess/EOAdaptorChannel.h
	add comment
	* EOAdaptors/PostgreSQLAdaptor/PostgreSQLChannel.m
	fix include for less warnings on mac
	numberOfAffectedRows: search reverse to cover "INSERT 0 1" case.
	The first zero is the OID number
	refactored primaryKeyForNewRowWithEntity:
	* EOAdaptors/PostgreSQLAdaptor/PostgreSQLContext.h/m
	disabled _primaryKeySequenceNameFormat
	* EOAdaptors/PostgreSQLAdaptor/PostgreSQLExpression.m
	fixed formatValue: forAttribute:
	* EOControl/EOEditingContext.m
	* EOControl/EOFaultHandler.m
	* EOControl/EOKeyValueQualifier.m
	* EOControl/EOUndoManager.m
	* EOControl/EOClassDescription.m
	* EOControl/EOQualifier.m
	* EOControl/EOOrQualifier.m
	fix include for less warnings on mac
	* EOControl/EOCustomObject.m
	use getCString:maxLength:encoding instead of getCString
	use setValue: forKey instead of takeValue: forKey:
	change text in exceptions a bit
	* EOControl/EOPrivate.h
	use setValue: forKey instead of takeValue: forKey:	



git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@30633 72102866-910b-0410-8b05-ffd578937521
2010-06-09 12:48:33 +00:00

1098 lines
28 KiB
Objective-C

/**
EOUtilities.m
Copyright (C) 2000-2002,2003,2004,2005 Free Software Foundation, Inc.
Author: Manuel Guesdon <mguesdon@orange-concept.com>
Date: Sep 2000
$Revision$
$Date$
<abstract></abstract>
This file is part of the GNUstep Database Library.
<license>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
</license>
**/
#include "config.h"
RCS_ID("$Id$")
#ifdef GNUSTEP
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSEnumerator.h>
#include <Foundation/NSException.h>
#include <Foundation/NSObjCRuntime.h>
#include <Foundation/NSDebug.h>
#else
#include <Foundation/Foundation.h>
#endif
#ifndef GNUSTEP
#include <GNUstepBase/GNUstep.h>
#include <GNUstepBase/NSDebug+GNUstepBase.h>
#include <GNUstepBase/NSObject+GNUstepBase.h>
#endif
#include <EOControl/EOKeyGlobalID.h>
#include <EOControl/EOQualifier.h>
#include <EOControl/EONull.h>
#include <EOControl/EOGenericRecord.h>
#include <EOControl/EODebug.h>
#include <EOAccess/EOAttribute.h>
#include <EOAccess/EORelationship.h>
#include <EOAccess/EOJoin.h>
#include <EOAccess/EOEntity.h>
#include <EOAccess/EOModel.h>
#include <EOAccess/EOModelGroup.h>
#include <EOAccess/EODatabase.h>
#include <EOAccess/EODatabaseContext.h>
#include <EOAccess/EODatabaseChannel.h>
#include <EOAccess/EOSQLExpression.h>
#include <EOAccess/EOAdaptorChannel.h>
#include <EOAccess/EOStoredProcedure.h>
#include <EOAccess/EOUtilities.h>
#include "EOPrivate.h"
NSString *EOMoreThanOneException = @"EOMoreThanOneException";
@implementation EOEditingContext (EOUtilities)
- (NSArray *)objectsForEntityNamed: (NSString *)entityName
{
NSArray *objects;
EOFetchSpecification *fetchSpecif;
NSAssert([entityName length] > 0, @"No entity name");
fetchSpecif = [EOFetchSpecification
fetchSpecificationWithEntityName: entityName
qualifier: nil
sortOrderings: nil];
objects = [self objectsWithFetchSpecification: fetchSpecif];
return objects;
}
- (NSArray *)objectsOfClass: (Class)classObject
{
EOEntity *entity;
NSArray *objects;
entity = [self entityForClass: classObject];
objects = [self objectsForEntityNamed: [entity name]];
return objects;
}
- (NSArray *)objectsWithFetchSpecificationNamed: (NSString *)fetchSpecName
entityNamed: (NSString *)entityName
bindings: (NSDictionary *)bindings
{
EOModelGroup *modelGroup;
EOFetchSpecification *unboundFetchSpec;
EOFetchSpecification *boundFetchSpec;
NSArray *results;
modelGroup = [self modelGroup];
unboundFetchSpec = [modelGroup fetchSpecificationNamed: fetchSpecName
entityNamed: entityName];
if ( !unboundFetchSpec )
{
[NSException raise: NSObjectNotAvailableException
format: @"%@: Fetch specification '%@' not found in entity named '%@'",
NSStringFromSelector(_cmd), fetchSpecName, entityName];
}
boundFetchSpec = [unboundFetchSpec fetchSpecificationWithQualifierBindings:
bindings];
results = [self objectsWithFetchSpecification: boundFetchSpec];
return results;
}
- (NSArray *)objectsForEntityNamed: (NSString *)entityName
qualifierFormat: (NSString *)format,...
{
EOQualifier *qualifier;
EOFetchSpecification *fetchSpec;
NSArray *results;
va_list args;
va_start(args, format);
qualifier = [EOQualifier qualifierWithQualifierFormat: format
varargList: args];
va_end(args);
fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:
entityName
qualifier: qualifier
sortOrderings: nil];
results = [self objectsWithFetchSpecification: fetchSpec];
return results;
}
- (NSArray *)objectsMatchingValue: (id)value
forKey: (NSString *)key
entityNamed: (NSString *)entityName
{
//OK
NSArray *objects;
NSDebugMLLog(@"gsdb", @"START value=%@ key=%@ entityName=%@",
value, key, entityName);
if (!value)
value=GDL2_EONull;
NSAssert(value, @"No Value"); //Transform it to EONull ?
NSAssert(key, @"No Key");
NSAssert([entityName length] > 0, @"No entity name");
objects = [self objectsMatchingValues:
[NSDictionary dictionaryWithObject: value
forKey: key]
entityNamed: entityName];
return objects;
//TC:
/*
EOKeyValueQualifier *qualifier;
EOFetchSpecification *fetch;
NSArray *newArray;
qualifier = [[EOKeyValueQualifier alloc]
initWithKey:key
operatorSelector:EOQualifierOperatorEqual
value:value];
fetch = [EOFetchSpecification fetchSpecificationWithEntityName:name
qualifier:[qualifier autorelease]
sortOrderings:nil];
newArray = [self objectsWithFetchSpecification:fetch];
return newArray;
*/
}
- (NSArray *)objectsMatchingValues: (NSDictionary *)values
entityNamed: (NSString *)entityName
{
//OK
NSArray *objects = nil;
EOFetchSpecification *fetchSpec;
EOQualifier *qualifier;
NSEnumerator *valuesEnum;
id key=nil;
NSMutableArray* kvQualifiers=nil;
NS_DURING
{
NSAssert([entityName length] > 0, @"No entity name");
valuesEnum = [values keyEnumerator];
kvQualifiers = [NSMutableArray array];
while ((key = [valuesEnum nextObject]))
{
id value = [values objectForKey: key];
EOKeyValueQualifier *tmpQualifier = [EOKeyValueQualifier
qualifierWithKey: key
operatorSelector:
@selector(isEqualTo:)
value: value];
[kvQualifiers addObject: tmpQualifier];
}
qualifier = [EOAndQualifier qualifierWithQualifierArray: kvQualifiers];
fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:
entityName
qualifier: qualifier
sortOrderings: nil];
objects = [self objectsWithFetchSpecification: fetchSpec];
}
NS_HANDLER
{
NSDebugMLog(@"exception in EOEditingContext (EOUtilities) objectsMatchingValues:entityNamed:", "");
NSLog(@"exception in EOEditingContext (EOUtilities) objectsMatchingValues:entityNamed:");
NSDebugMLog(@"exception=%@", localException);
NSLog(@"exception=%@", localException);
/* localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
@"In EOEditingContext (EOUtilities) objectsMatchingValues:entityNamed:");
*/
NSLog(@"exception=%@", localException);
[localException raise];
}
NS_ENDHANDLER;
return objects;
//TC:
/*
EOQualifier *qualifier;
EOFetchSpecification *fetchSpec;
NSArray *results;
qualifier = [EOQualifier qualifierToMatchAllValues:values];
fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:name qualifier:qualifier sortOrderings:nil];
results = [self objectsWithFetchSpecification:fetchSpec];
return results;
*/
}
- (id)objectWithFetchSpecificationNamed: (NSString *)fetchSpecName
entityNamed: (NSString *)entityName
bindings: (NSDictionary *)bindings
{
id object = nil;
int count;
NSArray *objects;
NSAssert([entityName length] > 0, @"No entity name");
objects = [self objectsWithFetchSpecificationNamed:fetchSpecName
entityNamed:entityName
bindings:bindings];
count = [objects count];
switch (count)
{
case 0:
[NSException raise: NSInvalidArgumentException
format: @"%@: No item selected for fetch specification %@ in entity %@ with bindings %@",
NSStringFromSelector(_cmd),
fetchSpecName,
entityName,
bindings];
break;
case 1:
object = [objects objectAtIndex: 0];
break;
default:
[NSException raise: EOMoreThanOneException
format: @"%@: Selected more than one item for fetch specification %@ in entity %@ with bindings %@",
NSStringFromSelector(_cmd),
fetchSpecName,
entityName,
bindings];
break;
}
return object;
}
- (id)objectForEntityNamed: (NSString *)entityName
qualifierFormat: (NSString *)format,...
{
id object = nil;
int count;
EOQualifier *qualifier;
EOFetchSpecification *fetchSpec;
NSArray *objects;
va_list args;
va_start(args, format);
qualifier = [EOQualifier qualifierWithQualifierFormat: format
varargList: args];
va_end(args);
fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:
entityName
qualifier: qualifier
sortOrderings: nil];
objects = [self objectsWithFetchSpecification: fetchSpec];
count = [objects count];
switch (count)
{
case 0:
[NSException raise: NSInvalidArgumentException
format: @"%@: No item selected for entity %@ qualified by %@",
NSStringFromSelector(_cmd),
entityName,
format];
break;
case 1:
object = [objects objectAtIndex: 0];
break;
default:
[NSException raise: EOMoreThanOneException
format: @"%@: Selected more than one item for entity %@ qualified by %@",
NSStringFromSelector(_cmd),
entityName,
format];
}
return object;
}
- (id)objectMatchingValue: (id)value
forKey: (NSString *)key
entityNamed: (NSString *)entityName
{
//OK
id object = nil;
int count;
NSArray *objects;
NSDebugMLLog(@"gsdb", @"START value=%@ key=%@ entityName=%@",
value, key, entityName);
NS_DURING //Debugging Purpose
{
NSAssert([entityName length] > 0, @"No entity name");
objects = [self objectsMatchingValue: value
forKey: key
entityNamed: entityName];
count = [objects count];
switch (count)
{
case 0:
[NSException raise: NSObjectNotAvailableException
format: @"%@: No %@ found with key %@ matching %@",
NSStringFromSelector(_cmd),
entityName,
key,
value];
break;
case 1:
object = [objects objectAtIndex: 0];
break;
default:
[NSException raise: EOMoreThanOneException
format: @"%@: Selected more than one %@ with key %@ matching %@",
NSStringFromSelector(_cmd),
entityName,
key,
value];
break;
}
}
NS_HANDLER
{
NSLog(@"exception in EOEditingContext (EOUtilities) objectMatchingValue:forKey:entityNamed:");
NSLog(@"exception=%@", localException);
/* localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
@"In EOEditingContext (EOUtilities) objectMatchingValue:forKey:entityNamed:");
*/
NSLog(@"exception=%@", localException);
[localException raise];
}
NS_ENDHANDLER;
return object;
}
- (id)objectMatchingValues: (NSDictionary *)values
entityNamed: (NSString *)entityName
{
id object = nil;
int count;
NSArray *objects;
NSAssert([entityName length] > 0, @"No entity name");
objects = [self objectsMatchingValues: values
entityNamed: entityName];
count = [objects count];
switch(count)
{
case 0:
[NSException raise: NSInvalidArgumentException
format: @"%@: No %@ found matching %@",
NSStringFromSelector(_cmd),
entityName,
values];
break;
case 1:
object = [objects objectAtIndex: 0];
break;
default:
[NSException raise: EOMoreThanOneException
format: @"%@: Selected more than one %@ matching %@",
NSStringFromSelector(_cmd),
entityName,
values];
break;
}
return object;
}
- (id)objectWithPrimaryKeyValue: (id)value
entityNamed: (NSString *)entityName
{
//OK
id object = nil;
EOEntity *entity;
NSAssert([entityName length] > 0, @"No entity name");
entity = [self entityNamed: entityName];
if (!entity)
[NSException raise: NSInvalidArgumentException
format: @"objectWithPrimaryKeyValue:%@ entityNamed:%@; no entity",
value,
entityName];
else
{
NSArray *primaryKeyAttributes = [entity primaryKeyAttributes];
if ([primaryKeyAttributes count] != 1)
{
[NSException raise: NSInvalidArgumentException
format: @"objectWithPrimaryKeyValue:%@ entityNamed:%@ may only be called for entities with one primary key attribute. For entities with compound primary keys, use objectWithPrimaryKey:entityNamed and provide a dictionary for the primary key.",
value,
entityName];
}
else
{
NSDictionary* pk;
if (!value)
value=GDL2_EONull;
pk = [NSDictionary dictionaryWithObject: value
forKey: [(EOAttribute*)[primaryKeyAttributes
objectAtIndex: 0]
name]];
object = [self objectWithPrimaryKey: pk
entityNamed: entityName];
}
}
return object;
}
- (id)objectWithPrimaryKey: (NSDictionary *)pkDict
entityNamed: (NSString *)entityName
{
//OK
id object = nil;
EOEntity *entity;
NSAssert([pkDict count] > 0, @"Empty primary key.");
NSAssert([entityName length] > 0, @"No entity name");
entity = [self entityNamed: entityName];
if (!entity)
[NSException raise: NSInvalidArgumentException
format: @"objectWithPrimaryKeyValue:%@ entityNamed:%@; no entity",
pkDict,
entityName];
else
{
EOGlobalID *gid = [entity globalIDForRow: pkDict];
object = [self faultForGlobalID: gid
editingContext: self];
}
return object;
}
- (NSArray *)rawRowsForEntityNamed: (NSString *)entityName
qualifierFormat: (NSString *)format,...
{
EOQualifier *qualifier;
EOFetchSpecification *fetchSpec;
NSArray *results;
va_list args;
va_start(args, format);
qualifier = [EOQualifier qualifierWithQualifierFormat: format
varargList: args];
va_end(args);
NSAssert([entityName length] > 0, @"No entity name");
fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:
entityName
qualifier: qualifier
sortOrderings: nil];
[fetchSpec setFetchesRawRows: YES];
results = [self objectsWithFetchSpecification: fetchSpec];
return results;
}
- (NSArray *)rawRowsMatchingValue: (id)value
forKey: (NSString *)key
entityNamed: (NSString *)entityName
{
NSDictionary *valueDict;
NSArray *results;
NSAssert([entityName length]>0,@"No entity name");
if (!value)
value=GDL2_EONull;
valueDict = [NSDictionary dictionaryWithObject: value
forKey: key];
results = [self rawRowsMatchingValues: valueDict
entityNamed: entityName];
return results;
}
- (NSArray *)rawRowsMatchingValues: (NSDictionary *)values
entityNamed: (NSString *)entityName
{
EOQualifier *qualifier;
EOFetchSpecification *fetchSpec;
NSArray *results;
NSAssert([entityName length] > 0, @"No entity name");
qualifier = [EOQualifier qualifierToMatchAllValues: values];
fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:
entityName
qualifier: qualifier
sortOrderings: nil];
[fetchSpec setFetchesRawRows: YES];
results = [self objectsWithFetchSpecification: fetchSpec];
return results;
}
- (NSArray *)rawRowsWithSQL: (NSString *)sqlString
modelNamed: (NSString *)name
{
EODatabaseContext *databaseContext;
EODatabaseChannel *databaseChannel;
EOAdaptorChannel *adaptorChannel;
NSMutableArray *results = nil;
NSArray *attributes = nil;
NSDictionary *row;
databaseContext = [self databaseContextForModelNamed: name];
[databaseContext lock];
NS_DURING
{
databaseChannel = [databaseContext availableChannel];
adaptorChannel = [databaseChannel adaptorChannel];
if (![adaptorChannel isOpen])
[adaptorChannel openChannel];
[adaptorChannel evaluateExpression:
[EOSQLExpression expressionForString: sqlString]];
attributes = [adaptorChannel describeResults];
[adaptorChannel setAttributesToFetch:attributes];
results = [NSMutableArray array];
while ((row = [adaptorChannel fetchRowWithZone: [self zone]]))
[results addObject: row];
[databaseContext unlock];
}
NS_HANDLER
{
[databaseContext unlock];
[localException raise];
}
NS_ENDHANDLER;
return results;
}
- (NSArray *)rawRowsWithStoredProcedureNamed: (NSString *)name
arguments: (NSDictionary *)args
{
EODatabaseContext *databaseContext;
EODatabaseChannel *databaseChannel;
EOAdaptorChannel *adaptorChannel;
EOStoredProcedure *storedProcedure;
NSMutableArray *results = nil;
NSDictionary *row;
storedProcedure = [[self modelGroup] storedProcedureNamed: name];
databaseContext = [self databaseContextForModelNamed:
[[storedProcedure model] name]];
[databaseContext lock];
NS_DURING
{
databaseChannel = [databaseContext availableChannel];
adaptorChannel = [databaseChannel adaptorChannel];
if (![adaptorChannel isOpen])
[adaptorChannel openChannel];
[adaptorChannel executeStoredProcedure: storedProcedure
withValues: args];
[adaptorChannel setAttributesToFetch: [adaptorChannel describeResults]];
results = [NSMutableArray array];
while ((row = [adaptorChannel fetchRowWithZone: [self zone]]))
[results addObject: row];
[databaseContext unlock];
}
NS_HANDLER
{
[databaseContext unlock];
[localException raise];
}
NS_ENDHANDLER;
return results;
}
- (NSDictionary *)executeStoredProcedureNamed: (NSString *)name
arguments: (NSDictionary *)args
{
EODatabaseContext *databaseContext;
EODatabaseChannel *databaseChannel;
EOAdaptorChannel *adaptorChannel;
EOStoredProcedure *storedProcedure;
NSDictionary *returnValues = nil;
storedProcedure = [[self modelGroup] storedProcedureNamed: name];
databaseContext = [self databaseContextForModelNamed:
[[storedProcedure model] name]];
[databaseContext lock];
NS_DURING
{
databaseChannel = [databaseContext availableChannel];
adaptorChannel = [databaseChannel adaptorChannel];
if (![adaptorChannel isOpen])
[adaptorChannel openChannel];
[adaptorChannel executeStoredProcedure: storedProcedure
withValues: args];
returnValues = [adaptorChannel
returnValuesForLastStoredProcedureInvocation];
[databaseContext unlock];
}
NS_HANDLER
{
[databaseContext unlock];
[localException raise];
}
NS_ENDHANDLER;
return returnValues;
}
- (id)objectFromRawRow: (NSDictionary *)row
entityNamed: (NSString *)entityName
{
NSAssert([entityName length] > 0, @"No entity name");
return [self faultForRawRow: row
entityNamed: entityName];
}
- (EODatabaseContext *)databaseContextForModelNamed: (NSString *)name
{
EOModelGroup *modelGroup;
EOModel *model;
EODatabaseContext *databaseContext;
modelGroup = [self modelGroup];
model = [modelGroup modelNamed: name];
if ( !model )
[NSException raise: NSInvalidArgumentException
format: @"%@: cannot find model named %@ associated with this EOEditingContext",
NSStringFromSelector(_cmd),
name];
databaseContext = [EODatabaseContext registeredDatabaseContextForModel: model
editingContext: self];
return databaseContext;
}
- (void)connectWithModelNamed: (NSString *)name
connectionDictionaryOverrides: (NSDictionary *)overrides
{
EOModel *model;
model = [[self modelGroup] modelNamed: name];
[self notImplemented: _cmd];
}
- (id)createAndInsertInstanceOfEntityNamed: (NSString *)entityName
{
id object;
EOClassDescription *classDescription;
classDescription = [EOClassDescription classDescriptionForEntityName:
entityName];
if (!classDescription)
[NSException raise: NSInvalidArgumentException
format: @"%@ could not find class description for entity named %@",
NSStringFromSelector(_cmd),
entityName];
object = [classDescription createInstanceWithEditingContext: self
globalID: nil
zone: [self zone]];
[self insertObject: object];
return object;
}
- (NSDictionary *)primaryKeyForObject: (id)object
{
EOKeyGlobalID *gid;
EOEntity *entity;
NSDictionary *newDict;
gid = (EOKeyGlobalID *)[self globalIDForObject: object];
entity = [self entityForObject: object];
newDict = [entity primaryKeyForGlobalID: gid];
return newDict;
}
- (NSDictionary *)destinationKeyForSourceObject: (id)object
relationshipNamed: (NSString*)name
{
EODatabaseContext *databaseContext;
EODatabase *database;
EOEntity *sourceEntity;
EORelationship *relationship;
NSArray *joins;
EOJoin *join;
NSString *sourceAttributeName;
NSString *destinationAttributeName;
NSDictionary *snapshot;
NSMutableDictionary *result = nil;
int i, count;
sourceEntity = [self entityForObject: object];
relationship = [sourceEntity relationshipNamed: name];
if (!relationship)
[NSException raise: NSInvalidArgumentException
format: @"%@: entity %@ does not have relationship named %@",
NSStringFromSelector(_cmd),
[sourceEntity name],
name];
databaseContext = [self databaseContextForModelNamed:
[[sourceEntity model] name]];
[databaseContext lock];
NS_DURING
{
database = [databaseContext database];
snapshot = [database snapshotForGlobalID:[self globalIDForObject:
object]];
joins = [relationship joins];
count = [joins count];
result = (NSMutableDictionary *)[NSMutableDictionary dictionary];
for (i = 0 ; i < count ; i++)
{
join = [joins objectAtIndex: i];
sourceAttributeName = [[join sourceAttribute] name];
destinationAttributeName = [[join destinationAttribute] name];
[result setObject: [snapshot objectForKey: sourceAttributeName]
forKey: destinationAttributeName];
}
[databaseContext unlock];
}
NS_HANDLER
{
[databaseContext unlock];
[localException raise];
}
NS_ENDHANDLER;
return result;
}
- (id)localInstanceOfObject: (id)object
{
EOGlobalID *gid;
id newInstance;
gid = [[object editingContext] globalIDForObject:object];
newInstance = [self faultForGlobalID: gid
editingContext: self];
return newInstance;
}
- (NSArray *)localInstancesOfObjects: (NSArray *)objects
{
NSMutableArray *array;
int i, count = [objects count];
id obj;
array = [NSMutableArray arrayWithCapacity: count];
for (i = 0; i < count; i++)
{
obj = [self localInstanceOfObject: [objects objectAtIndex: i]];
[array addObject: obj];
}
return array;
}
- (EOModelGroup *)modelGroup
{
EOObjectStore *rootObjectStore;
EOObjectStoreCoordinator *objectStoreCoordinator;
EOModelGroup *modelGroup;
rootObjectStore = [self rootObjectStore];
if (![rootObjectStore isKindOfClass: [EOObjectStoreCoordinator class]])
[NSException raise: NSInvalidArgumentException
format: @"%@: an EOEditingContext's root object store must be an EOObjectStoreCoordinator for this method to function.",
NSStringFromSelector(_cmd)];
objectStoreCoordinator = (EOObjectStoreCoordinator *)rootObjectStore;
modelGroup = [objectStoreCoordinator modelGroup];
return modelGroup;
}
- (EOEntity *)entityNamed: (NSString *)entityName
{
EOEntity *entity;
EOModelGroup *modelGroup;
NSAssert([entityName length] > 0, @"No entity name");
modelGroup = [self modelGroup];
NSAssert(modelGroup, @"No model group");
entity = [modelGroup entityNamed: entityName];
if (!entity)
[NSException raise: NSInvalidArgumentException
format: @"%@: could not find entity named:%@",
NSStringFromSelector(_cmd),
entityName];
return entity;
}
- (EOEntity *)entityForClass: (Class)classObject
{
EOModelGroup *modelGroup;
NSArray *models;
EOModel *model;
int modelCount;
NSArray *entities;
EOEntity *entity;
NSString *className;
NSString *entityClassName;
int i, j, entityCount;
EOEntity *result = nil;
BOOL matchesClassName;
className = NSStringFromClass(classObject);
modelGroup = [self modelGroup];
models = [modelGroup models];
modelCount = [models count];
for (i = 0 ; i < modelCount ; i++)
{
model = [models objectAtIndex: i];
entities = [model entities];
entityCount = [entities count];
for (j = 0 ; j < entityCount ; j++)
{
entity = [entities objectAtIndex: j];
entityClassName = [entity className];
matchesClassName = [className isEqualToString: entityClassName];
// Java class names in the Objective-C run-time system use '/' instead of '.' to separate package names, so we also check for a class name in which we replaced '.' with '/'.
if (!matchesClassName
&& ([entityClassName rangeOfString:@"."].length != 0))
matchesClassName = [className
isEqualToString:
[[entityClassName componentsSeparatedByString: @"."]
componentsJoinedByString: @"/"]];
if (matchesClassName)
{
if (result)
[NSException raise: EOMoreThanOneException
format: @"%@ found more than one entity for class named %@",
NSStringFromSelector(_cmd),
className];
else
result = entity;
}
}
}
if (!result)
[NSException raise: NSObjectNotAvailableException
format: @"%@ could not find entity for class named %@",
NSStringFromSelector(_cmd), className];
return result;
}
- (EOEntity *)entityForObject: (id)object
{
EOClassDescription *classDesc;
EOEntity *newEntity;
classDesc = [(EOGenericRecord *)object classDescription];
if ([classDesc isKindOfClass: [EOEntityClassDescription class]] == NO)
[NSException raise: NSInvalidArgumentException
format: @"%@ - %@: the object's class description must be an EOEntityClassDescription",
NSStringFromSelector(_cmd),
object];
newEntity = [(EOEntityClassDescription *)classDesc entity];
return newEntity;
}
@end
@implementation EOFetchSpecification (EOAccess)
+ (EOFetchSpecification *)fetchSpecificationNamed: (NSString *)name
entityNamed: (NSString *)entityName
{
EOFetchSpecification *newEOFetchSpecification = nil;
EOModelGroup *anModelGroup;
anModelGroup = [EOModelGroup defaultGroup];
if (anModelGroup)
newEOFetchSpecification = [anModelGroup fetchSpecificationNamed: name
entityNamed: entityName];
return newEOFetchSpecification;
}
@end