* EOAdaptors/PostgreSQLAdaptor/PostgreSQLChannel.m:

respect GNUstep coding standard (curly brackets placement, indentation)
  use IMP for some -objectAtIndex calls
* EOControl/EONSAddOns.h
  add -overrideEntriesWithObjectsFromDictionary:forKeys:
  add +diffOldArray:newArray:returnsRemovedValues:addedValues:
* EOControl/EONSAddOns.h
  add -overrideEntriesWithObjectsFromDictionary:forKeys:
  add +diffOldArray:newArray:returnsRemovedValues:addedValues:
  use IMP for some -objectAtIndex calls
  use NSUInteger for count and indexes
  rewrite -containsIdenticalObjectsWithArray: to use diffOldArray:...
* EOControl/EODetailDataSource.m
  fix -editingContext
* EOAccess/EODatabaseContext.m
  use IMP for some -objectAtIndex calls
  rewrite -faultForGlobalID:editingContext:
  optimize -recordChangesInEditingContext:
  rewrite part of -databaseOperationForObject:


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@37920 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
mguesdon 2014-05-29 12:06:02 +00:00
parent 8be4f65ada
commit 64604f3337
6 changed files with 710 additions and 675 deletions

View file

@ -1,3 +1,23 @@
2014-05-29 Manuel Guesdon <mguesdon@orange-concept.com>
* EOAdaptors/PostgreSQLAdaptor/PostgreSQLChannel.m:
respect GNUstep coding standard (curly brackets placement, indentation)
use IMP for some -objectAtIndex calls
* EOControl/EONSAddOns.h
add -overrideEntriesWithObjectsFromDictionary:forKeys:
add +diffOldArray:newArray:returnsRemovedValues:addedValues:
* EOControl/EONSAddOns.h
add -overrideEntriesWithObjectsFromDictionary:forKeys:
add +diffOldArray:newArray:returnsRemovedValues:addedValues:
use IMP for some -objectAtIndex calls
use NSUInteger for count and indexes
rewrite -containsIdenticalObjectsWithArray: to use diffOldArray:...
* EOControl/EODetailDataSource.m
fix -editingContext
* EOAccess/EODatabaseContext.m
use IMP for some -objectAtIndex calls
rewrite -faultForGlobalID:editingContext:
optimize -recordChangesInEditingContext:
rewrite part of -databaseOperationForObject:
2014-05-22 Manuel Guesdon <mguesdon@orange-concept.com>
* EOAccess/EODatabaseContext.m
implement _objectFaultWithSnapshot:relationship:editingContext:

View file

@ -447,12 +447,11 @@ static Class _contextClass = Nil;
if (count>0)
{
NSUInteger i = 0;
IMP oaiIMP=[_registeredChannels methodForSelector: @selector(objectAtIndex:)];
IMP oaiIMP=NULL;
for (i = 0 ; !busy && i < count; i++)
{
EODatabaseChannel *channel = GDL2_ObjectAtIndexWithImp(_registeredChannels,oaiIMP,i);
EODatabaseChannel *channel = GDL2_ObjectAtIndexWithImpPtr(_registeredChannels,&oaiIMP,i);
busy = [channel isFetchInProgress];
}
};
@ -690,19 +689,16 @@ May raise an exception if transaction has began or if you want pessimistic lock
}
/** return entity corresponding to 'globalID' **/
//MG2014: OK
- (id) entityForGlobalID: (EOGlobalID *)globalID
{
NSString *entityName;
entityName = [(EOKeyGlobalID *)globalID entityName];
if ((_lastEntity) && (entityName == [_lastEntity name]))
{
return _lastEntity;
}
ASSIGN(_lastEntity, [_database entityNamed: entityName]);
NSString *entityName=[(EOKeyGlobalID *)globalID entityName];
if (_lastEntity==nil
|| ![[_lastEntity name] isEqualToString:entityName])
{
ASSIGN(_lastEntity, [_database entityNamed: entityName]);
}
return _lastEntity;
}
@ -746,66 +742,43 @@ May raise an exception if transaction has began or if you want pessimistic lock
}
/** Get a fault for 'globalID' **/
//MG2014: OK
- (id)faultForGlobalID: (EOGlobalID *)globalID
editingContext: (EOEditingContext *)context
{
//Seems OK
EOClassDescription *classDescription = nil;
EOEntity *entity;
id object = nil;
BOOL isFinal;
isFinal = [(EOKeyGlobalID *)globalID isFinal];
entity = [self entityForGlobalID: globalID];
NSAssert(entity, @"no entity");
classDescription = [entity classDescriptionForInstances];
object = [classDescription createInstanceWithEditingContext: context
globalID: globalID
zone: NULL];
NSAssert1(object, @"No Object. classDescription=%@", classDescription);
/*mirko: NO
NSDictionary *pk;
NSEnumerator *pkEnum;
NSString *pkKey;
NSArray *classPropertyNames;
classPropertyNames = [entity classPropertyNames];
pk = [entity primaryKeyForGlobalID:(EOKeyGlobalID *)globalID];
pkEnum = [pk keyEnumerator];
while ((pkKey = [pkEnum nextObject]))
if (![globalID isKindOfClass:[EOKeyGlobalID class]])
{
if ([classPropertyNames containsObject:pkKey] == YES)
[obj takeStoredValue:[pk objectForKey:pkKey]
forKey:pkKey];
[NSException raise: @"NSIllegalStateException"
format:@"%s: The globalID %@ must be an EOKeyGlobalID to be able to construct a fault.",
__PRETTY_FUNCTION__,
globalID];
}
*/
if ([(EOKeyGlobalID *)globalID areKeysAllNulls])
NSWarnLog(@"All key of globalID %p (%@) are nulls",
globalID,
globalID);
[self _turnToFault: object
gid: globalID
editingContext: context
isComplete: isFinal];//??
EOEditingContext_recordObjectGlobalIDWithImpPtr(context,NULL,object,globalID);
else
{
EOEntity* entity = [self entityForGlobalID: globalID];
NSAssert(entity, @"no entity");
if ([(EOKeyGlobalID *)globalID isFinal])
{
object = [[entity classDescriptionForInstances]
createInstanceWithEditingContext: context
globalID: globalID
zone: NULL];
[self _turnToFault: object
gid: globalID
editingContext: context
isComplete: YES];
}
else
{
object = [self _fetchSingleObjectForEntity:entity
globalID:globalID
editingContext:context];
}
EOEditingContext_recordObjectGlobalIDWithImpPtr(context,NULL,object,globalID);
}
return object;
}
@ -848,56 +821,58 @@ classPropertyNames = [entity classPropertyNames];
return obj;
}
//MG2014: TODO: implement use of _currentGlobalID
- (void)initializeObject: (id)object
withGlobalID: (EOGlobalID *)globalID
editingContext: (EOEditingContext *)context
{
NSDictionary * snapDict = nil;
NSDictionary * snapshot = nil;
EOEntity * entity = nil;
/*if (globalID == _currentGlobalID)
{
snapshot = _currentSnapshot;
entity = _lastEntity;
}
else*/
{
if ([globalID isTemporary])
return;
else
{
snapshot = [self snapshotForGlobalID:globalID];
if ([(EOKeyGlobalID *)globalID isFinal])
{
entity = [self entityForGlobalID:globalID];
}
else
{
object = [context objectForGlobalID:globalID];
if (object==nil)
{
[NSException raise: NSInternalInconsistencyException
format: @"%s No object for gid %@ in %@",
__PRETTY_FUNCTION__, globalID, context];
}
entity = [_database entityForObject:object];
}
}
}
/*
TODO use this stuff -- dw
if (globalID == _currentGlobalID)
{
snapDict = _currentSnapshot;
entity = _lastEntity;
} else ...
*/
if ([globalID isTemporary])
{
return;
}
snapDict = [self snapshotForGlobalID:globalID];
if ([(EOKeyGlobalID *)globalID isFinal])
{
entity = [self entityForGlobalID:globalID];
} else {
object = [context objectForGlobalID:globalID];
if (!object)
if (snapshot==nil)
{
[NSException raise: NSInternalInconsistencyException
format: @"%s No object for gid %@ in %@", __PRETTY_FUNCTION__, globalID, context];
format: @"%s No snapshot for gid %@",
__PRETTY_FUNCTION__, globalID];
}
entity = [_database entityForObject:object];
}
if (!snapDict)
{
[NSException raise: NSInternalInconsistencyException
format: @"%s No snapshot for gid %@", __PRETTY_FUNCTION__, globalID];
} else {
[self initializeObject: object
row: snapDict
entity: entity
else
{
[self initializeObject: object
row: snapshot
entity: entity
editingContext: context];
[_database incrementSnapshotCountForGlobalID:globalID];
}
[_database incrementSnapshotCountForGlobalID:globalID];
}
}
- (void) _objectsChanged: (NSNotification*)notification
@ -1760,13 +1735,17 @@ classPropertyNames = [entity classPropertyNames];
@implementation EODatabaseContext(EOCooperatingObjectStoreSupport)
//MG2014: TODO: implement use of _currentGlobalID
- (BOOL)ownsGlobalID: (EOGlobalID *)globalID
{
if ([globalID isKindOfClass: [EOKeyGlobalID class]] &&
[_database entityNamed: [(EOKeyGlobalID*) globalID entityName]])
return YES;
BOOL ownsGlobalID=NO;
/*if (_currentGlobalID == eoglobalid)
ownsGlobalID=YES;
else*/ if ([globalID isKindOfClass: [EOKeyGlobalID class]]
&& [_database entityNamed: [(EOKeyGlobalID*) globalID entityName]] != nil)
ownsGlobalID=YES;
return NO;
return ownsGlobalID;
}
- (BOOL)ownsObject: (id)object
@ -2155,6 +2134,7 @@ forDatabaseOperation:(EODatabaseOperation *)op
}
}
//MG2014: OK
- (void)recordChangesInEditingContext
{
//_EOAssertSafeMultiThreadedAccess
@ -2272,47 +2252,49 @@ forDatabaseOperation:(EODatabaseOperation *)op
{
NSArray* updatedSnapValues = (NSArray*) updatedSnapValue;
NSArray* currentSnapValues = (NSArray*) currentSnapValue;
NSArray * oldValues = nil;
if (updatedSnapValues != currentSnapValues
&& ![currentSnapValues isEqualToArray:updatedSnapValues]) // TODO: check if isEqual is ok too.
//Here we use optimized method
//Think you may have more than 1000 objects in each of these arrays so imagine a 1000x1000 comparisons...
BOOL isDiff=[NSArray diffOldArray:currentSnapValues
newArray:updatedSnapValues
returnsRemovedValues:&oldValues
addedValues:NULL];
if (isDiff)
{
NSMutableArray * snapsToUse = nil;
if (!updatedSnapValues)
snapsToUse = (NSMutableArray*) currentSnapValues;
else if (currentSnapValues)
NSUInteger oldValuesCount=[oldValues count];
if (oldValuesCount>0)
{
snapsToUse = [NSMutableArray arrayWithArray:currentSnapValues];
[snapsToUse removeObjectsInArray:updatedSnapValues];
}
if (_useToManyCaching
&& [snapsToUse count] > 0)
{
EODatabaseOperation * updatedEoDbOp = [self databaseOperationForObject:eo];
NSUInteger valCount = [updatedSnapValues count];
NSMutableArray * globalids = [NSMutableArray arrayWithCapacity:valCount];
NSUInteger x = 0;
for (; x < valCount; x++)
if (_useToManyCaching)
{
EOCustomObject * updatedEo = [updatedSnapValues objectAtIndex:x];
EOGlobalID * globalid = [_editingContext globalIDForObject:updatedEo];
IMP oldValues_oaiIMP=NULL;
IMP aoIMP=NULL;
EODatabaseOperation * updatedEoDbOp = [self databaseOperationForObject:eo];
NSUInteger valCount = [oldValues count];
NSMutableArray * globalIDs = [NSMutableArray arrayWithCapacity:valCount];
NSUInteger x = 0;
if (!globalid
|| [globalid isTemporary])
for (; x < valCount; x++)
{
globalids = nil;
break;
}
[globalids addObject:globalid];
}
[updatedEoDbOp recordToManySnapshot:globalids
relationshipName:[relationship name]];
EOCustomObject * updatedEo = GDL2_ObjectAtIndexWithImpPtr(oldValues,&oldValues_oaiIMP,x);
EOGlobalID * globalID = [_editingContext globalIDForObject:updatedEo];
if (!globalID
|| [globalID isTemporary])
{
globalIDs = nil;
break;
}
GDL2_AddObjectWithImpPtr(globalIDs,&aoIMP,globalID);
}
[updatedEoDbOp recordToManySnapshot:globalIDs
relationshipName:[relationship name]];
}
[self nullifyAttributesInRelationship:substRelationship
sourceObject:eo
destinationObjects:oldValues];
}
[self nullifyAttributesInRelationship:substRelationship
sourceObject:eo
destinationObjects:snapsToUse];
}
}
else if (updatedSnapValue != currentSnapValue)
@ -2384,50 +2366,52 @@ forDatabaseOperation:(EODatabaseOperation *)op
{
NSArray * updatedSnapValues = (NSArray*) updatedSnapValue;
NSArray * currentSnapValues = (NSArray*) currentSnapValue;
NSMutableArray * snaps = nil;
if (updatedSnapValues != currentSnapValues
&& ![currentSnapValues isEqualToArray:updatedSnapValues])
{
if (!currentSnapValues)
snaps = (NSMutableArray*) updatedSnapValues;
else
{
snaps = [NSMutableArray arrayWithArray:updatedSnapValues];
[snaps removeObjectsInArray:currentSnapValues];
}
if (_useToManyCaching
&& [snaps count] > 0)
{
EODatabaseOperation * updatedEoDbOp = [self databaseOperationForObject:updatedEO];
NSUInteger valCount = [updatedSnapValues count];
NSUInteger y = 0;
NSMutableArray * globalids = [NSMutableArray arrayWithCapacity:valCount];
for (; y < valCount; y++)
{
EOGlobalID * gid = [_editingContext globalIDForObject:[updatedSnapValues objectAtIndex:y]];
if (!gid
|| [gid isTemporary])
{
globalids = nil;
break;
}
[globalids addObject:gid];
}
NSArray * newValues = nil;
[updatedEoDbOp recordToManySnapshot:globalids
relationshipName:[updatedEntityRel name]];
//Here we use optimized method
//Think you may have more than 1000 objects in each of these arrays so imagine a 1000x1000 comparisons...
BOOL isDiff=[NSArray diffOldArray:currentSnapValues
newArray:updatedSnapValues
returnsRemovedValues:NULL
addedValues:&newValues];
if (isDiff)
{
NSUInteger newValuesCount=[newValues count];
if (newValuesCount>0)
{
if (_useToManyCaching )
{
IMP updatedSnapValues_oaiIMP=NULL;
IMP aoIMP=NULL;
EODatabaseOperation * updatedEoDbOp = [self databaseOperationForObject:updatedEO];
NSUInteger valCount = [updatedSnapValues count];
NSUInteger x = 0;
NSMutableArray * globalIDs = [NSMutableArray arrayWithCapacity:valCount];
for (; x < valCount; x++)
{
EOCustomObject * anObject = GDL2_ObjectAtIndexWithImpPtr(updatedSnapValues,&updatedSnapValues_oaiIMP,x);
EOGlobalID * globalID = [_editingContext globalIDForObject:anObject];
if (!globalID
|| [globalID isTemporary])
{
globalIDs = nil;
break;
}
GDL2_AddObjectWithImpPtr(globalIDs,&aoIMP,globalID);
}
//TODO: why we should record updatedSnapValues snapshot only when there's newValues ?
[updatedEoDbOp recordToManySnapshot:globalIDs
relationshipName:[updatedEntityRel name]];
}
[self relayAttributesInRelationship:substitutionRel
sourceObject:updatedEO
destinationObjects:newValues];
}
[self relayAttributesInRelationship:substitutionRel
sourceObject:updatedEO
destinationObjects:snaps];
}
}
else if (updatedSnapValue != currentSnapValue)
else if (updatedSnapValue != currentSnapValue)
{
[self relayAttributesInRelationship:substitutionRel
sourceObject:updatedEO
@ -3121,9 +3105,6 @@ Raises an exception is the adaptor is unable to perform the operations.
sourceObject: (id)sourceObject
destinationObject: (id)destinationObject
{
NSDebugMLLog(@"EODatabaseContext", @"destinationObject=%@",
destinationObject);
if (destinationObject)
{
//Get SourceObject database operation
@ -3142,11 +3123,6 @@ Raises an exception is the adaptor is unable to perform the operations.
[relationship _sourceToDestinationKeyMap]; //{destinationKeys = (customerCode); sourceKeys = (code); }
BOOL foreignKeyInDestination = [relationship foreignKeyInDestination];
NSDebugMLLog(@"EODatabaseContext", @"sourceToDestinationKeyMap=%@",
sourceToDestinationKeyMap);
NSDebugMLLog(@"EODatabaseContext", @"foreignKeyInDestination=%d",
foreignKeyInDestination);
if (foreignKeyInDestination)
{
NSArray *destinationKeys = [sourceToDestinationKeyMap
@ -3334,159 +3310,72 @@ Raises an exception is the adaptor is unable to perform the operations.
- (EODatabaseOperation*)databaseOperationForObject: (id)object
{
//OK
EODatabaseOperation *databaseOpe = nil;
EOGlobalID *gid = EODatabaseContext_globalIDForObjectWithImpPtr(self,NULL,object);
NS_DURING // for trace purpose
databaseOpe = [self databaseOperationForGlobalID: gid];
if (databaseOpe == nil)
{
EOGlobalID *gid = nil;
if ([object isKindOfClass: [EOGenericRecord class]])
NSDebugMLLog(@"EODatabaseContext", @"dictionary=%@ ",
[object debugDictionaryDescription]);
gid = EODatabaseContext_globalIDForObjectWithImpPtr(self,NULL,object);
databaseOpe = [self databaseOperationForGlobalID: gid]; //OK
if (!databaseOpe)//OK
{
EOEntity *entity = [_database entityForObject: object]; //OK
NSArray *primaryKeyAttributes = [entity primaryKeyAttributes]; //OK
NSDictionary *snapshot = nil;
NSArray *classPropertyNames = nil;
NSArray *dbSnapshotKeys = nil;
int i = 0;
int propNamesCount = 0;
int snapKeyCount = 0;
NSMutableDictionary *row = nil;
NSMutableDictionary *newRow = nil;
NSDebugMLLog(@"EODatabaseContext", @"entity name=%@",
[entity name]);
NSDebugMLLog(@"EODatabaseContext",
@"primaryKeyAttributes=%@",
primaryKeyAttributes);
databaseOpe = [EODatabaseOperation
databaseOperationWithGlobalID: gid
object: object
entity: entity]; //OK
NSDebugMLLog(@"EODatabaseContext",
@"CREATED databaseOpe=%@\nfor object %p %@",
databaseOpe, object, object);
snapshot = EODatabaseContext_snapshotForGlobalIDWithImpPtr(self,NULL,gid);//OK
NSDebugMLLog(@"EODatabaseContext", @"snapshot %p=%@",
snapshot, snapshot);
if (!snapshot)
snapshot = [NSDictionary dictionary];
[databaseOpe setDBSnapshot: snapshot];
NSDebugMLLog(@"EODatabaseContext",@"object=%p databaseOpe=%@",
object,databaseOpe);
classPropertyNames = [entity classPropertyNames]; //OK (code, a3code, numcode, toLabel)
NSDebugMLLog(@"EODatabaseContext",
@"classPropertyNames=%@", classPropertyNames);
propNamesCount = [classPropertyNames count];
NSDebugMLLog(@"EODatabaseContext", @"propNamesCount=%d",
(int)propNamesCount);
//TODO: rewrite code: don't use temporary "row"
row = (NSMutableDictionary*)[NSMutableDictionary dictionary];
NSDebugMLLog(@"EODatabaseContext",@"object %p (class %@)=%@ ",
object,[object class],object);
/*if ([object isKindOfClass: [EOGenericRecord class]])
NSDebugMLLog(@"EODatabaseContext", @"dictionary=%@ ",
[object debugDictionaryDescription]);*/
if (propNamesCount>0)
{
IMP oaiIMP=[classPropertyNames methodForSelector: @selector(objectAtIndex:)];
for (i = 0; i < propNamesCount; i++)
{
id value = nil;
NSString *key = GDL2_ObjectAtIndexWithImp(classPropertyNames,oaiIMP,i);
/*NO !!
if ([attribute isKindOfClass:[EOAttribute class]] == NO)
continue;
// if ([attribute isFlattened] == NO)
*/
value = [object storedValueForKey: key]; //OK
NSDebugMLLog(@"EODatabaseContext", @"key=%@ value=%@",
key, value);
if (!value)
{
value = GDL2_EONull;
[[[entity attributeNamed: key] validateValue: &value]
raise];
}
NSDebugMLLog(@"EODatabaseContext", @"key=%@ value=%@",
key, value);
[row setObject: value
forKey: key];
}
};
newRow = [[NSMutableDictionary alloc]
initWithDictionary: snapshot
copyItems: NO];
dbSnapshotKeys = [entity dbSnapshotKeys]; //OK (numcode, code, a3code)
NSDebugMLLog(@"EODatabaseContext", @"dbSnapshotKeys=%@",
dbSnapshotKeys);
snapKeyCount = [dbSnapshotKeys count];
if (snapKeyCount>0)
{
IMP oaiIMP=[dbSnapshotKeys methodForSelector: @selector(objectAtIndex:)];
for (i = 0; i < snapKeyCount; i++)
{
id key = GDL2_ObjectAtIndexWithImp(dbSnapshotKeys,oaiIMP,i);
id value = [row objectForKey: key]; //Really this key ?
NSDebugMLLog(@"EODatabaseContext", @"key=%@ value=%@",
key, value);
// NSAssert1(value,@"No value for %@",key);
if (value)
[newRow setObject: value
forKey: key];
}
};
[databaseOpe setNewRow: newRow];
[self recordDatabaseOperation: databaseOpe];
RELEASE(newRow);
}
}
NS_HANDLER
{
[localException raise];
}
NS_ENDHANDLER;
EOEntity *entity = [_database entityForObject: object];
if (entity != nil)
{
NSArray *primaryKeyAttributes = [entity primaryKeyAttributes];
if ([primaryKeyAttributes count]==0)
{
[NSException raise: @"NSIllegalStateException"
format:@"databaseOperationForObject: attempted to process an EO mapped to entity '%@' which has no primary key defined. All entities must have a primary key specified. You should run the EOModeler consistency checker on the model containing this entity and perform whatever actions are necessary to ensure that the model is in a consistent state.",
[entity name]];
}
else
{
NSDictionary *snapshot = nil;
NSArray *classPropertyNames = nil;
NSUInteger propNamesCount = 0;
NSMutableDictionary *objectStoredKVs = nil;
NSMutableDictionary *newRow = nil;
databaseOpe = [EODatabaseOperation
databaseOperationWithGlobalID: gid
object: object
entity: entity];
snapshot = EODatabaseContext_snapshotForGlobalIDWithImpPtr(self,NULL,gid);
if (snapshot == nil)
snapshot = [NSDictionary dictionary];
[databaseOpe setDBSnapshot: snapshot];
classPropertyNames = [entity classPropertyNames];
propNamesCount = [classPropertyNames count];
objectStoredKVs = (NSMutableDictionary*)[NSMutableDictionary dictionaryWithCapacity:propNamesCount];
if (propNamesCount>0)
{
NSUInteger i=0;
IMP oaiIMP=NULL;
for (i = 0; i < propNamesCount; i++)
{
NSString *key = GDL2_ObjectAtIndexWithImpPtr(classPropertyNames,&oaiIMP,i);
id value = [object storedValueForKey: key];
[objectStoredKVs setObject: (value==nil ? GDL2_EONull : value)
forKey: key];
}
};
newRow = AUTORELEASE([[NSMutableDictionary alloc]
initWithDictionary: snapshot
copyItems: NO]);
[newRow overrideEntriesWithObjectsFromDictionary:objectStoredKVs
forKeys:[entity dbSnapshotKeys]];
[databaseOpe setNewRow: newRow];
[self recordDatabaseOperation: databaseOpe];
}
}
}
return databaseOpe;
}
@ -6094,7 +5983,6 @@ compareUsingEntityNames(id left, id right, void* vpSortOrders)
// self, object];
// }
return pk;
}

View file

@ -1749,99 +1749,100 @@ each key
NSMutableArray *attributes = [NSMutableArray array];
// if we just check isFetchInProgress here we fail on raw sql fetches. -- dw
if ((!_isFetchInProgress) && (!_evaluateExprInProgress)) {
[NSException raise: NSInternalInconsistencyException
format: @"%s -- %@ 0x%p: attempt to describe results with no fetch in progress",
__PRETTY_FUNCTION__,
NSStringFromClass([self class]),
self];
} else {
int colsNumber;
colsNumber=_pgResult ? PQnfields(_pgResult): 0;
int i;
for (i = 0; i < colsNumber; i++)
if (!_isFetchInProgress
&& !_evaluateExprInProgress)
{
EOAttribute *attribute
= AUTORELEASE([PSQLA_alloc(EOAttribute) init]);
NSString *externalType;
NSString *valueClass = @"NSString";
NSString *valueType = nil;
[NSException raise: NSInternalInconsistencyException
format: @"%s -- %@ 0x%p: attempt to describe results with no fetch in progress",
__PRETTY_FUNCTION__,
NSStringFromClass([self class]),
self];
if (_origAttributes)
{
EOAttribute *origAttr = (EOAttribute *) [_origAttributes objectAtIndex:i];
[attribute setName: [origAttr name]];
[attribute setColumnName: [origAttr columnName]];
[attribute setExternalType: [origAttr externalType]];
[attribute setValueType: [origAttr valueType]];
[attribute setValueClassName: [origAttr valueClassName]];
}
else
{
NSNumber *externalTypeNumber;
externalTypeNumber = [NSNumber numberWithLong: PQftype(_pgResult, i)];
externalType = [_oidToTypeName objectForKey:externalTypeNumber];
if (!externalType)
[NSException raise: PostgreSQLException
format: @"cannot find type for Oid = %d",
PQftype(_pgResult, i)];
[attribute setName: [NSString stringWithCString:PQfname(_pgResult,i)
encoding:NSASCIIStringEncoding]];
[attribute setColumnName: @"unknown"];
[attribute setExternalType: externalType];
//TODO: Optimize ?
if ([externalType isEqual: @"bool"])
valueClass = @"NSNumber", valueType = @"c";
else if ([externalType isEqual: @"char"])
valueClass = @"NSNumber", valueType = @"c";
else if ([externalType isEqual: @"dt"])
valueClass = @"NSCalendarDate", valueType = nil;
else if ([externalType isEqual: @"date"])
valueClass = @"NSCalendarDate", valueType = nil;
else if ([externalType isEqual: @"time"])
valueClass = @"NSCalendarDate", valueType = nil;
else if ([externalType isEqual: @"float4"])
valueClass = @"NSNumber", valueType = @"f";
else if ([externalType isEqual: @"float8"])
valueClass = @"NSNumber", valueType = @"d";
else if ([externalType isEqual: @"int2"])
valueClass = @"NSNumber", valueType = @"s";
else if ([externalType isEqual: @"int4"])
valueClass = @"NSNumber", valueType = @"i";
else if ([externalType isEqual: @"int8"] || [externalType isEqual: @"bigint"])
valueClass = @"NSNumber", valueType = @"u";
else if ([externalType isEqual: @"oid"])
valueClass = @"NSNumber", valueType = @"l";
else if ([externalType isEqual: @"varchar"])
valueClass = @"NSString", valueType = nil;
else if ([externalType isEqual: @"bpchar"])
valueClass = @"NSString", valueType = nil;
else if ([externalType isEqual: @"text"])
valueClass = @"NSString", valueType = nil;
/* else if ([externalType isEqual:@"cid"])
valueClass = @"NSNumber", valueType = @"";
else if ([externalType isEqual:@"tid"])
valueClass = @"NSNumber", valueType = @"";
else if ([externalType isEqual:@"xid"])
valueClass = @"NSNumber", valueType = @"";*/
[attribute setValueType: valueType];
[attribute setValueClassName: valueClass];
}
[attributes addObject:attribute];
}
}
else
{
IMP origAttributesOAI=NULL; // objectAtIndex:
int colsNumber=_pgResult ? PQnfields(_pgResult): 0;
int i;
for (i = 0; i < colsNumber; i++)
{
EOAttribute *attribute
= AUTORELEASE([PSQLA_alloc(EOAttribute) init]);
NSString *externalType;
NSString *valueClass = @"NSString";
NSString *valueType = nil;
if (_origAttributes)
{
EOAttribute *origAttr = (EOAttribute *) PSQLA_ObjectAtIndexWithImpPtr(_origAttributes,&origAttributesOAI,i);
[attribute setName: [origAttr name]];
[attribute setColumnName: [origAttr columnName]];
[attribute setExternalType: [origAttr externalType]];
[attribute setValueType: [origAttr valueType]];
[attribute setValueClassName: [origAttr valueClassName]];
}
else
{
NSNumber *externalTypeNumber;
externalTypeNumber = [NSNumber numberWithLong: PQftype(_pgResult, i)];
externalType = [_oidToTypeName objectForKey:externalTypeNumber];
if (!externalType)
[NSException raise: PostgreSQLException
format: @"cannot find type for Oid = %d",
PQftype(_pgResult, i)];
[attribute setName: [NSString stringWithCString:PQfname(_pgResult,i)
encoding:NSASCIIStringEncoding]];
[attribute setColumnName: @"unknown"];
[attribute setExternalType: externalType];
//TODO: Optimize ?
if ([externalType isEqual: @"bool"])
valueClass = @"NSNumber", valueType = @"c";
else if ([externalType isEqual: @"char"])
valueClass = @"NSNumber", valueType = @"c";
else if ([externalType isEqual: @"dt"])
valueClass = @"NSCalendarDate", valueType = nil;
else if ([externalType isEqual: @"date"])
valueClass = @"NSCalendarDate", valueType = nil;
else if ([externalType isEqual: @"time"])
valueClass = @"NSCalendarDate", valueType = nil;
else if ([externalType isEqual: @"float4"])
valueClass = @"NSNumber", valueType = @"f";
else if ([externalType isEqual: @"float8"])
valueClass = @"NSNumber", valueType = @"d";
else if ([externalType isEqual: @"int2"])
valueClass = @"NSNumber", valueType = @"s";
else if ([externalType isEqual: @"int4"])
valueClass = @"NSNumber", valueType = @"i";
else if ([externalType isEqual: @"int8"] || [externalType isEqual: @"bigint"])
valueClass = @"NSNumber", valueType = @"u";
else if ([externalType isEqual: @"oid"])
valueClass = @"NSNumber", valueType = @"l";
else if ([externalType isEqual: @"varchar"])
valueClass = @"NSString", valueType = nil;
else if ([externalType isEqual: @"bpchar"])
valueClass = @"NSString", valueType = nil;
else if ([externalType isEqual: @"text"])
valueClass = @"NSString", valueType = nil;
/* else if ([externalType isEqual:@"cid"])
valueClass = @"NSNumber", valueType = @"";
else if ([externalType isEqual:@"tid"])
valueClass = @"NSNumber", valueType = @"";
else if ([externalType isEqual:@"xid"])
valueClass = @"NSNumber", valueType = @"";*/
[attribute setValueType: valueType];
[attribute setValueClassName: valueClass];
}
[attributes addObject:attribute];
}
}
return attributes;
}

View file

@ -204,12 +204,12 @@ RCS_ID("$Id$")
- (EOEditingContext *)editingContext
{
/*
* 4.5 documented as _masterObject or nil
* in 5.x this is documented as returning the master data source or nil
* seems to be a documentation error in 4.5
*/
return [_masterDataSource editingContext];
if (_masterDataSource!=nil)
return [_masterDataSource editingContext];
else if (_masterObject != nil)
return [_masterObject editingContext];
else
return nil;
}
- (NSArray *)fetchObjects

View file

@ -85,6 +85,10 @@ GDL2_Activate(Class sup, Class cls);
withObject: (id)object2;
- (BOOL)containsIdenticalObjectsWithArray: (NSArray *)array;
+(BOOL)diffOldArray:(NSArray*)oldArray
newArray:(NSArray*)newArray
returnsRemovedValues:(NSArray**)removedValues
addedValues:(NSArray**)addedValues;
@end
@interface NSObject (EOCompareOnName)
@ -146,6 +150,11 @@ GDL2_Activate(Class sup, Class cls);
- (void) translateFromKeys:(NSArray *) currentKeys
toKeys:(NSArray *) newKeys;
/**
* Override self values with values from dict for keys
*/
-(void)overrideEntriesWithObjectsFromDictionary:(NSDictionary*)dict
forKeys:(NSArray*)keys;
@end
@interface NSDictionary (EOAdditions)

View file

@ -155,43 +155,29 @@ GDL2_Activate(Class sup, Class cls)
if (array)
{
int i, count = [array count];
volatile id object = nil;
IMP oaiIMP=NULL;
NSUInteger count = [array count];
results = [NSMutableArray array];
//OPTIMIZE
NS_DURING
{
for(i = 0; i < count; i++)
{
id result;
object = [array objectAtIndex: i];
result = [self performSelector: sel
withObject: (id)object];
if (!result)
result = defaultResult;
NSAssert3(result,
@"%@: No result for object %@ resultOfPerformingSelector:\"%s\" withEachObjectInArray:",
self,
object,
sel_getName(sel));
[results addObject: result];
}
}
NS_HANDLER
{
NSWarnLog(@"object %p %@ may not support %@",
object,
[object class],
NSStringFromSelector(sel));
NSLog(@"%@ %@",localException,[localException userInfo]);
[localException raise];
}
NS_ENDHANDLER;
if (count>0)
{
NSUInteger i=0;
for(i = 0; i < count; i++)
{
id object = GDL2_ObjectAtIndexWithImpPtr(array,&oaiIMP,i);
id result = [self performSelector: sel
withObject: object];
if (!result)
result = defaultResult;
NSAssert3(result,
@"%@: No result for object %@ resultOfPerformingSelector:\"%s\" withEachObjectInArray:",
self,
object,
sel_getName(sel));
[results addObject: result];
}
}
}
return results;
@ -217,50 +203,29 @@ GDL2_Activate(Class sup, Class cls)
defaultResult: (id)defaultResult
{
NSMutableArray *results=[NSMutableArray array];
int i, count = [self count];
volatile id object = nil;
NSUInteger count = [self count];
NSDebugMLLog(@"gsdb", @"self:%p (%@) results:%p (%@)",
self, [self class], results, [results class]);
//OPTIMIZE
NS_DURING
if (count>0)
{
IMP oaiIMP=NULL;
NSUInteger i =0;
for(i = 0; i < count; i++)
{
id result;
object = [self objectAtIndex: i];
result = [object performSelector: sel];
if (!result)
result = defaultResult;
NSAssert3(result,
@"%@: No result for object %@ resultOfPerformingSelector:\"%s\"",
self,
object,
sel_getName(sel));
[results addObject: result]; //TODO What to do if nil ??
}
{
id object = GDL2_ObjectAtIndexWithImpPtr(self,&oaiIMP,i);
id result = [object performSelector: sel];
if (!result)
result = defaultResult;
NSAssert3(result,
@"%@: No result for object %@ resultOfPerformingSelector:\"%s\"",
self,
object,
sel_getName(sel));
[results addObject: result];
}
}
NS_HANDLER
{
NSWarnLog(@"object %p %@ may doesn't support %@",
object,
[object class],
NSStringFromSelector(sel));
NSLog(@"%@ (%@)", localException, [localException reason]);
[localException raise];
}
NS_ENDHANDLER;
NSDebugMLLog(@"gsdb", @"self:%p (%@) results:%p (%@)",
self, [self class], results, [results class]);
return results;
}
@ -277,19 +242,16 @@ GDL2_Activate(Class sup, Class cls)
defaultResult:(id)defaultResult
{
NSMutableArray *results = [NSMutableArray array];
int i, count = [self count];
volatile id object = nil;
//OPTIMIZE
NS_DURING
NSUInteger count = [self count];
if (count>0)
{
IMP oaiIMP=NULL;
NSUInteger i=0;
for(i = 0; i < count; i++)
{
id result;
object = [self objectAtIndex: i];
result = [object performSelector: sel
withObject: obj1];
id object = GDL2_ObjectAtIndexWithImpPtr(self,&oaiIMP,i);
id result = [object performSelector: sel
withObject: obj1];
if (!result)
result = defaultResult;
@ -300,21 +262,9 @@ GDL2_Activate(Class sup, Class cls)
object,
sel_getName(sel));
[results addObject: result]; //TODO What to do if nil ??
[results addObject: result];
}
}
NS_HANDLER
{
NSWarnLog(@"object %p %@ may doesn't support %@",
object,
[object class],
NSStringFromSelector(sel));
NSLog(@"%@ (%@)", localException, [localException reason]);
[localException raise];
}
NS_ENDHANDLER;
return results;
}
@ -335,20 +285,18 @@ GDL2_Activate(Class sup, Class cls)
defaultResult: (id)defaultResult
{
NSMutableArray *results = [NSMutableArray array];
int i, count = [self count];
volatile id object = nil;
NSUInteger count = [self count];
//OPTIMIZE
NS_DURING
if (count>0)
{
IMP oaiIMP=NULL;
NSUInteger i=0;
for(i = 0; i < count; i++)
{
id result;
object = [self objectAtIndex: i];
result = [object performSelector: sel
withObject: obj1
withObject: obj2];
id object = GDL2_ObjectAtIndexWithImpPtr(self,&oaiIMP,i);
id result = [object performSelector: sel
withObject: obj1
withObject: obj2];
if (!result)
result = defaultResult;
@ -359,21 +307,9 @@ GDL2_Activate(Class sup, Class cls)
object,
sel_getName(sel));
[results addObject: result]; //TODO What to do if nil ??
[results addObject: result];
}
}
NS_HANDLER
{
NSWarnLog(@"object %p %@ may doesn't support %@",
object,
[object class],
NSStringFromSelector(sel));
NSLog(@"%@ (%@)", localException, [localException reason]);
[localException raise];
}
NS_ENDHANDLER;
return results;
}
@ -382,17 +318,17 @@ GDL2_Activate(Class sup, Class cls)
{
//Verify: mutable/non mutable,..
NSArray *result = nil;
unsigned int selfCount = [self count];
NSUInteger selfCount = [self count];
if (selfCount > 0) //else return nil
{
unsigned int arrayCount = [array count];
NSUInteger arrayCount = [array count];
if (arrayCount == 0) //Nothing to exclude ?
result = self;
else
{
NSUInteger i;
NSUInteger i = 0;
for (i = 0; i < selfCount; i++)
{
@ -421,11 +357,12 @@ GDL2_Activate(Class sup, Class cls)
if (selfCount > 0 && _object) //else return nil
{
int i;
NSUInteger i=0;
IMP oaiIMP=NULL;
for (i = 0; i < selfCount; i++)
{
id object = [self objectAtIndex: i];
id object = GDL2_ObjectAtIndexWithImpPtr(self,&oaiIMP,i);
if (object != _object)
{
@ -444,26 +381,23 @@ GDL2_Activate(Class sup, Class cls)
withObject: (id)object2
{
NSArray *array = nil;
int count;
count = [self count];
NSUInteger count = [self count];
if (count > 0)
{
int i;
id o = nil;
NSMutableArray *tmpArray = [NSMutableArray arrayWithCapacity: count];
IMP oaiIMP=NULL;
NSUInteger i = 0;
NSMutableArray* tmpArray = [NSMutableArray arrayWithCapacity: count];
for (i = 0; i < count; i++)
{
o = [self objectAtIndex: i];
id o = GDL2_ObjectAtIndexWithImpPtr(self,&oaiIMP,i);
if ([o isEqual: object1])
[tmpArray addObject: object2];
else
[tmpArray addObject: o];
}
array = [NSArray arrayWithArray: tmpArray];
}
else
@ -476,40 +410,186 @@ GDL2_Activate(Class sup, Class cls)
**/
- (BOOL)containsIdenticalObjectsWithArray: (NSArray *)array
{
BOOL ret = NO;
int selfCount = [self count];
int arrayCount = [array count];
return ![NSArray diffOldArray:self
newArray:array
returnsRemovedValues:NULL
addedValues:NULL];
}
if (selfCount == arrayCount)
#define EO_MAX_OBJECTS_FROM_STACK 64
/**
* Macro to manage memory for chunks of code that need to work with
* arrays of items. Use this to start the block of code using
* the array and EO_ENDITEMBUF() to end it. The idea is to ensure that small
* arrays are allocated on the stack (for speed), but large arrays are
* allocated from the heap (to avoid stack overflow).
*/
#define EO_BEGINITEMBUF(P, S, T) { \
T P ## _ibuf[(S) <= EO_MAX_OBJECTS_FROM_STACK ? (S) : 0]; \
T *P ## _base = ((S) <= EO_MAX_OBJECTS_FROM_STACK) ? P ## _ibuf \
: (T*)NSZoneMalloc(NSDefaultMallocZone(), (S) * sizeof(T)); \
T *(P) = P ## _base;
/**
* Macro to manage memory for chunks of code that need to work with
* arrays of items. Use EO_BEGINITEMBUF() to start the block of code using
* the array and this macro to end it.
*/
#define EO_ENDITEMBUF(P) \
if (P ## _base != P ## _ibuf) \
NSZoneFree(NSDefaultMallocZone(), P ## _base); \
}
/**
* Macro to manage memory for chunks of code that need to work with
* arrays of objects. Use this to start the block of code using
* the array and EO_ENDIDBUF() to end it. The idea is to ensure that small
* arrays are allocated on the stack (for speed), but large arrays are
* allocated from the heap (to avoid stack overflow).
*/
#define EO_BEGINIDBUF(P, S) EO_BEGINITEMBUF(P, S, id)
/**
* Macro to manage memory for chunks of code that need to work with
* arrays of objects. Use EO_BEGINIDBUF() to start the block of code using
* the array and this macro to end it.
*/
#define EO_ENDIDBUF(P) EO_ENDITEMBUF(P)
//Returns YES if the 2 arrays don't contains exactly identical objects (compared by address) (i.e. only the order may change)
//Optimized for end addition/removing
+(BOOL)diffOldArray:(NSArray*)oldArray
newArray:(NSArray*)newArray
returnsRemovedValues:(NSArray**)removedValues
addedValues:(NSArray**)addedValues
{
BOOL isDiff=NO;
if (removedValues!=NULL)
*removedValues=nil;
if (addedValues!=NULL)
*addedValues=nil;
if (oldArray==newArray)
{
BOOL foundInArray[arrayCount];
int i, j;
memset(foundInArray, 0, sizeof(BOOL) * arrayCount);
ret = YES;
for (i = 0; ret && i < selfCount; i++)
{
id selfObj = [self objectAtIndex: i];
ret = NO;
for (j = 0; j < arrayCount; j++)
{
id arrayObj = [array objectAtIndex: j];
if (arrayObj == selfObj && !foundInArray[j])
{
foundInArray[j] = YES;
ret = YES;
break;
}
}
}
//Same array: do nothing
isDiff=NO;
}
else
{
NSUInteger oldArrayCount = [oldArray count];
NSUInteger newArrayCount = [newArray count];
if (oldArrayCount==0)
{
if (newArrayCount==0) // oldArrayCount==0 && newArrayCount==0
{
//same are empty
isDiff=NO;
}
else // oldArrayCount==0 && newArrayCount>0
{
//No old array values
isDiff=YES;
if (addedValues!=NULL)
{
if ([newArray isKindOfClass:GDL2_NSMutableArrayClass])
*addedValues=AUTORELEASE([newArray shallowCopy]);
else
*addedValues=AUTORELEASE(RETAIN(newArray));
}
}
}
else if (newArrayCount==0) // oldArrayCount>0 && newArrayCount==0
{
//no new array values
isDiff=YES;
if (removedValues!=NULL)
{
if ([oldArray isKindOfClass:GDL2_NSMutableArrayClass])
*removedValues=AUTORELEASE([oldArray shallowCopy]);
else
*removedValues=AUTORELEASE(RETAIN(oldArray));
}
}
else // oldArrayCount>0 && newArrayCount>0
{
//Start deep work
NSUInteger minCount=(oldArrayCount<newArrayCount ? oldArrayCount : newArrayCount);
EO_BEGINIDBUF(oldObjects,oldArrayCount);
EO_BEGINIDBUF(newObjects,newArrayCount);
[oldArray getObjects: oldObjects];
[newArray getObjects: newObjects];
return ret;
//Find for 1st diff
NSUInteger i=0;
NSUInteger start=minCount;
for(i=0;i<minCount;i++)
{
if (oldObjects[i]!=newObjects[i])
{
start=i;
break;
}
}
if (start==minCount
&& oldArrayCount==newArrayCount)
{
//No diff found at the begining and same array size
isDiff=NO;
}
else
{
//NSLog(@"X DIFF ARRAY start at %d",start);
NSUInteger maxCount=(oldArrayCount>newArrayCount ? oldArrayCount : newArrayCount);
maxCount-=start;
EO_BEGINIDBUF(tmpObjects,maxCount);
// Find removed values
NSUInteger oi=0;
NSUInteger ni=0;
i=0;
for(oi=start;oi<oldArrayCount;oi++)
{
id o=oldObjects[oi];
for(ni=start;ni<newArrayCount && newObjects[ni]!=o;ni++);
NSCAssert(i<maxCount,@"Pb");
if (ni>=newArrayCount)//Not found ?
tmpObjects[i++]=o;
}
if (i>0)
{
isDiff=YES;
if (removedValues!=NULL)
{
*removedValues=[NSArray arrayWithObjects:tmpObjects
count:i];
}
}
// Find added values
i=0;
for(ni=start;ni<newArrayCount;ni++)
{
id n=newObjects[ni];
for(oi=start;oi<oldArrayCount && oldObjects[oi]!=n;oi++);
NSCAssert(i<maxCount,@"Pb");
if (oi>=oldArrayCount)//Not found ?
tmpObjects[i++]=n;
}
if (i>0)
{
isDiff=YES;
if (addedValues!=NULL)
{
*addedValues=[NSArray arrayWithObjects:tmpObjects
count:i];
}
}
EO_ENDIDBUF(tmpObjects);
}
EO_ENDIDBUF(newObjects);
EO_ENDIDBUF(oldObjects);
}
}
return isDiff;
}
@end
@ -571,7 +651,7 @@ GDL2_Activate(Class sup, Class cls)
- (NSString *)initialCapitalizedString
{
unichar *chars;
unsigned int length = [self length];
NSUInteger length = [self length];
chars = NSZoneMalloc(NSDefaultMallocZone(),length * sizeof(unichar));
[self getCharacters: chars];
@ -689,27 +769,38 @@ GDL2_Activate(Class sup, Class cls)
+ (NSMutableDictionary *) dictionaryWithDictionary:(NSDictionary *)otherDictionary
keys:(NSArray*)keys
{
if (!keys)
{
return [NSMutableDictionary dictionary];
} else {
NSUInteger keyCount = [keys count];
NSUInteger i = 0;
NSMutableDictionary * mDict = [NSMutableDictionary dictionaryWithCapacity:keyCount];
for (; i < keyCount; i++) {
NSString * key = [keys objectAtIndex:i];
id value = [otherDictionary valueForKey:key];
if (!value) {
value = GDL2_EONull;
}
[mDict setObject:value
forKey:key];
NSMutableDictionary* mDict=nil;
if (keys==nil)
{
mDict=[NSMutableDictionary dictionary];
}
return mDict;
}
else
{
NSUInteger keyCount = [keys count];
if (keyCount==0)
{
mDict=[NSMutableDictionary dictionary];
}
else
{
IMP oaiIMP=NULL;
NSUInteger i = 0;
mDict = [NSMutableDictionary dictionaryWithCapacity:keyCount];
for (; i < keyCount; i++)
{
NSString * key = GDL2_ObjectAtIndexWithImpPtr(keys,&oaiIMP,i);
id value = [otherDictionary valueForKey:key];
if (!value)
value = GDL2_EONull;
[mDict setObject:value
forKey:key];
}
}
}
return mDict;
}
// "translateFromKeys:toKeys:",
@ -718,45 +809,72 @@ GDL2_Activate(Class sup, Class cls)
toKeys:(NSArray *) newKeys
{
NSUInteger count = [currentKeys count];
NSString * nullPlaceholder = @"__EOAdditionsDummy__";
NSMutableArray * buffer;
NSUInteger i;
if(count != [newKeys count])
{
[NSException raise: NSInvalidArgumentException
format: @"%s key arrays must contain equal number of keys", __PRETTY_FUNCTION__];
}
buffer = [NSMutableArray arrayWithCapacity:count];
for (i = 0; i < count; i++)
{
id key = [currentKeys objectAtIndex:i];
id value = [self objectForKey:key];
if (!value)
if (count != [newKeys count])
{
value = nullPlaceholder;
[buffer addObject:value];
} else {
[buffer addObject:value];
[self removeObjectForKey:key];
[NSException raise: NSInvalidArgumentException
format: @"%s key arrays must contain equal number of keys", __PRETTY_FUNCTION__];
}
}
[self removeAllObjects];
for (i = 0; i < count; i++)
{
id value = [buffer objectAtIndex:i];
if(value != nullPlaceholder)
else
{
[self setObject:value
forKey:[newKeys objectAtIndex:i]];
}
}
IMP oaiIMP=NULL;
NSMutableArray* buffer = [NSMutableArray arrayWithCapacity:count];
NSUInteger i = 0;
NSString * nullPlaceholder = @"__EOAdditionsDummy__";
for (i = 0; i < count; i++)
{
id key = GDL2_ObjectAtIndexWithImpPtr(currentKeys,&oaiIMP,i);
id value = [self objectForKey:key];
if (!value)
{
value = nullPlaceholder;
[buffer addObject:value];
}
else
{
[buffer addObject:value];
[self removeObjectForKey:key];
}
}
[self removeAllObjects];
for (i = 0; i < count; i++)
{
id value = [buffer objectAtIndex:i];
if(value != nullPlaceholder)
{
[self setObject:value
forKey:[newKeys objectAtIndex:i]];
}
}
}
}
/**
* Override self values with values from dict for keys
*/
-(void)overrideEntriesWithObjectsFromDictionary:(NSDictionary*)dict
forKeys:(NSArray*)keys
{
NSUInteger keysCount=[keys count];
if (keysCount>0)
{
IMP oaiIMP=NULL;
NSUInteger i=0;
for(i=0;i<keysCount;i++)
{
id key = GDL2_ObjectAtIndexWithImpPtr(keys,&oaiIMP,i);
id value = [dict objectForKey:key];
if (value != nil)
{
[self setObject:value
forKey:key];
}
}
}
}
@end
@ -767,16 +885,16 @@ GDL2_Activate(Class sup, Class cls)
{
NSArray * values = [self allValues];
NSUInteger count = [values count];
NSUInteger i = 0;
for (; i < count; i++)
{
if (([values objectAtIndex:i] == GDL2_EONull))
if (count>0)
{
return YES;
IMP oaiIMP=NULL;
NSUInteger i = 0;
for (; i < count; i++)
{
if (GDL2_ObjectAtIndexWithImpPtr(values,&oaiIMP,i) == GDL2_EONull)
return YES;
}
}
}
return NO;
}
@ -786,18 +904,17 @@ GDL2_Activate(Class sup, Class cls)
NSUInteger count = [keys count];
if (count > 0)
{
dict = [NSMutableDictionary dictionaryWithCapacity:count];
NSUInteger i;
for (i = 0; i < count; i++)
{
NSString * key = [keys objectAtIndex:i];
[dict setObject:GDL2_EONull
forKey: key];
IMP oaiIMP=NULL;
NSUInteger i = 0;
dict = [NSMutableDictionary dictionaryWithCapacity:count];
for (i = 0; i < count; i++)
{
NSString * key = GDL2_ObjectAtIndexWithImpPtr(keys,&oaiIMP,i);
[dict setObject:GDL2_EONull
forKey: key];
}
}
}
return dict;
}