mirror of
https://github.com/gnustep/libs-gdl2.git
synced 2025-04-22 12:55:44 +00:00
* 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:
parent
8be4f65ada
commit
64604f3337
6 changed files with 710 additions and 675 deletions
20
ChangeLog
20
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue