mirror of
https://github.com/gnustep/libs-gdl2.git
synced 2025-04-25 13:50:54 +00:00
Fixes inEOAttribute.m and EOKeyValueARchiver.m
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@21153 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
8bab203b96
commit
9c4a91f7ce
4 changed files with 420 additions and 173 deletions
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
||||||
|
2005-04-20 Manuel Guesdon <mguesdon@orange-concept.com>
|
||||||
|
|
||||||
|
* EOControl/EOPriv.h: added GDL2_allocWithZone()
|
||||||
|
* EOAccess/EOAttribute.m:
|
||||||
|
o fixed -validateValue: rewritten following
|
||||||
|
David Ayers's advices to handle EONull values
|
||||||
|
validation and fix width validation
|
||||||
|
o fixed -newValueForBytes:length: retain problems and
|
||||||
|
wrong invocation target
|
||||||
|
o fixed -newValueForBytes:length:encoding: retain
|
||||||
|
problems and wrong invocation target
|
||||||
|
o added comments and doc
|
||||||
|
o added allowsNull in EOAttribute -description
|
||||||
|
* EOControl/EOKeyValueArchiver.m: fixed int and bool
|
||||||
|
archiving following David Ayers's comments (produce
|
||||||
|
NSNumber instead of NSString)
|
||||||
|
|
||||||
2005-04-24 Matt Rice <ratmice@yahoo.com>
|
2005-04-24 Matt Rice <ratmice@yahoo.com>
|
||||||
|
|
||||||
* EOAdaptors/Postgres95/Postgres95Adaptor.m: Removed externalTypeNames
|
* EOAdaptors/Postgres95/Postgres95Adaptor.m: Removed externalTypeNames
|
||||||
|
|
|
@ -441,10 +441,11 @@ RCS_ID("$Id$")
|
||||||
[self columnName],
|
[self columnName],
|
||||||
[self definition]];
|
[self definition]];
|
||||||
|
|
||||||
dscr = [dscr stringByAppendingFormat: @"valueClassName=%@ valueType=%@ externalType=%@ isReadOnly=%s isDerived=%s isFlattened=%s>",
|
dscr = [dscr stringByAppendingFormat: @"valueClassName=%@ valueType=%@ externalType=%@ allowsNull=%s isReadOnly=%s isDerived=%s isFlattened=%s>",
|
||||||
[self valueClassName],
|
[self valueClassName],
|
||||||
[self valueType],
|
[self valueType],
|
||||||
[self externalType],
|
[self externalType],
|
||||||
|
([self allowsNull] ? "YES" : "NO"),
|
||||||
([self isReadOnly] ? "YES" : "NO"),
|
([self isReadOnly] ? "YES" : "NO"),
|
||||||
([self isDerived] ? "YES" : "NO"),
|
([self isDerived] ? "YES" : "NO"),
|
||||||
([self isFlattened] ? "YES" : "NO")];
|
([self isFlattened] ? "YES" : "NO")];
|
||||||
|
@ -1078,17 +1079,18 @@ return nexexp
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an NSString or a custom-class value object
|
* Returns an NSData or a custom-class value object
|
||||||
* from the supplied set of bytes.
|
* from the supplied set of bytes.
|
||||||
* The Adaptor calls this method during value creation
|
* The Adaptor calls this method during value creation
|
||||||
* when fetching objects from the database.
|
* when fetching objects from the database.
|
||||||
* For efficiency, the returned value is NOT autoreleased.
|
* For efficiency, the returned value is NOT autoreleased.
|
||||||
|
*
|
||||||
|
* NB: The documentation of the reference implementation
|
||||||
|
* mistakenly claims that it returns an NSString.
|
||||||
**/
|
**/
|
||||||
- (id)newValueForBytes: (const void *)bytes
|
- (id)newValueForBytes: (const void *)bytes
|
||||||
length: (int)length
|
length: (int)length
|
||||||
{
|
{
|
||||||
NSMethodSignature *aSignature;
|
|
||||||
NSInvocation *anInvocation;
|
|
||||||
NSData *value = nil;
|
NSData *value = nil;
|
||||||
Class valueClass = [self _valueClass];
|
Class valueClass = [self _valueClass];
|
||||||
|
|
||||||
|
@ -1097,43 +1099,79 @@ return nexexp
|
||||||
switch (_argumentType)
|
switch (_argumentType)
|
||||||
{
|
{
|
||||||
case EOFactoryMethodArgumentIsNSData:
|
case EOFactoryMethodArgumentIsNSData:
|
||||||
|
{
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
value = [GDL2_alloc(NSData) initWithBytes: bytes length: length];
|
value = [GDL2_alloc(NSData) initWithBytes: bytes length: length];
|
||||||
|
|
||||||
|
// If we have a value factiry method, call it to get the final value
|
||||||
if(_valueFactoryMethod != NULL)
|
if(_valueFactoryMethod != NULL)
|
||||||
{
|
{
|
||||||
//TODO: doc says that the returned value is autoreleased !!
|
NSData* tmp = value;
|
||||||
|
// valueFactoryMethod returns an autoreleased value
|
||||||
value = [(id)valueClass performSelector: _valueFactoryMethod
|
value = [(id)valueClass performSelector: _valueFactoryMethod
|
||||||
withObject: [value autorelease]];
|
withObject: value];
|
||||||
|
if (value != value)
|
||||||
|
{
|
||||||
|
RETAIN(value);
|
||||||
|
RELEASE(tmp);
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case EOFactoryMethodArgumentIsBytes:
|
case EOFactoryMethodArgumentIsBytes:
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
{
|
||||||
value = [valueClass allocWithZone: 0];
|
NSMethodSignature *aSignature = nil;
|
||||||
|
NSInvocation *anInvocation = nil;
|
||||||
|
|
||||||
|
// TODO: verify with WO
|
||||||
|
NSAssert2(_valueFactoryMethod,
|
||||||
|
@"No _valueFactoryMethod (valueFactoryMethodName=%@) in attribute %@",
|
||||||
|
_valueFactoryMethodName,self);
|
||||||
|
|
||||||
|
// First find signature for method
|
||||||
aSignature =
|
aSignature =
|
||||||
[valueClass
|
[valueClass
|
||||||
instanceMethodSignatureForSelector: _valueFactoryMethod];
|
methodSignatureForSelector: _valueFactoryMethod];
|
||||||
|
|
||||||
|
// Create the invocation object
|
||||||
anInvocation
|
anInvocation
|
||||||
= [NSInvocation invocationWithMethodSignature: aSignature];
|
= [NSInvocation invocationWithMethodSignature: aSignature];
|
||||||
|
|
||||||
|
// Put the selector
|
||||||
[anInvocation setSelector: _valueFactoryMethod];
|
[anInvocation setSelector: _valueFactoryMethod];
|
||||||
[anInvocation setTarget: value];
|
|
||||||
|
// The target is the custom value class
|
||||||
|
[anInvocation setTarget: valueClass];
|
||||||
|
|
||||||
|
// arguments are buffer pointer and length
|
||||||
[anInvocation setArgument: &bytes atIndex: 2];
|
[anInvocation setArgument: &bytes atIndex: 2];
|
||||||
[anInvocation setArgument: &length atIndex: 3];
|
[anInvocation setArgument: &length atIndex: 3];
|
||||||
[anInvocation invoke];
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
// Let's invoke the method
|
||||||
|
[anInvocation invoke];
|
||||||
|
|
||||||
|
// Get the returned value
|
||||||
|
[anInvocation getReturnValue: &value];
|
||||||
|
|
||||||
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
|
// valueFactoryMethod returns an autoreleased value
|
||||||
|
RETAIN(value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case EOFactoryMethodArgumentIsNSString:
|
case EOFactoryMethodArgumentIsNSString:
|
||||||
|
// TODO: verify with WO
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!value)
|
if(!value)
|
||||||
|
{
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
value = [GDL2_alloc(NSData) initWithBytes: bytes length: length];
|
value = [GDL2_alloc(NSData) initWithBytes: bytes length: length];
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -1149,9 +1187,7 @@ return nexexp
|
||||||
length: (int)length
|
length: (int)length
|
||||||
encoding: (NSStringEncoding)encoding
|
encoding: (NSStringEncoding)encoding
|
||||||
{
|
{
|
||||||
NSMethodSignature *aSignature;
|
NSString* value = nil;
|
||||||
NSInvocation *anInvocation;
|
|
||||||
id value = nil;
|
|
||||||
Class valueClass = [self _valueClass];
|
Class valueClass = [self _valueClass];
|
||||||
|
|
||||||
if (valueClass != Nil && valueClass != GDL2_NSStringClass)
|
if (valueClass != Nil && valueClass != GDL2_NSStringClass)
|
||||||
|
@ -1160,40 +1196,79 @@ return nexexp
|
||||||
{
|
{
|
||||||
case EOFactoryMethodArgumentIsNSString:
|
case EOFactoryMethodArgumentIsNSString:
|
||||||
{
|
{
|
||||||
NSData *data;
|
NSData *data = nil;
|
||||||
NSString *string;
|
NSString *string = nil;
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
|
||||||
data = AUTORELEASE([(GDL2_alloc(NSData)) initWithBytes: bytes
|
data = AUTORELEASE([(GDL2_alloc(NSData)) initWithBytes: bytes
|
||||||
length: length]);
|
length: length]);
|
||||||
string = AUTORELEASE([(GDL2_alloc(NSString)) initWithData: data
|
|
||||||
encoding: encoding]);
|
|
||||||
|
|
||||||
|
string = [(GDL2_alloc(NSString)) initWithData: data
|
||||||
|
encoding: encoding];
|
||||||
|
|
||||||
|
// If we have a value factiry method, call it to get the final value
|
||||||
|
if(_valueFactoryMethod != NULL)
|
||||||
|
{
|
||||||
value = [((id)valueClass) performSelector: _valueFactoryMethod
|
value = [((id)valueClass) performSelector: _valueFactoryMethod
|
||||||
withObject: string];
|
withObject: string];
|
||||||
|
if ( value != string)
|
||||||
|
{
|
||||||
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
|
RETAIN(value);
|
||||||
|
RELEASE(string);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
|
value = string;
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EOFactoryMethodArgumentIsBytes:
|
case EOFactoryMethodArgumentIsBytes:
|
||||||
{
|
{
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
NSMethodSignature *aSignature = nil;
|
||||||
value = [valueClass alloc];
|
NSInvocation *anInvocation = nil;
|
||||||
|
|
||||||
|
// TODO: verify with WO
|
||||||
|
NSAssert2(_valueFactoryMethod,
|
||||||
|
@"No _valueFactoryMethod (valueFactoryMethodName=%@) in attribute %@",
|
||||||
|
_valueFactoryMethodName,self);
|
||||||
|
|
||||||
|
// First find signature for method
|
||||||
aSignature
|
aSignature
|
||||||
= [valueClass instanceMethodSignatureForSelector: _valueFactoryMethod];
|
= [valueClass methodSignatureForSelector: _valueFactoryMethod];
|
||||||
|
|
||||||
|
// Create the invocation object
|
||||||
anInvocation
|
anInvocation
|
||||||
= [NSInvocation invocationWithMethodSignature: aSignature];
|
= [NSInvocation invocationWithMethodSignature: aSignature];
|
||||||
|
|
||||||
|
// Put the selector
|
||||||
[anInvocation setSelector: _valueFactoryMethod];
|
[anInvocation setSelector: _valueFactoryMethod];
|
||||||
[anInvocation setTarget: value];
|
|
||||||
|
// The target is the custom value class
|
||||||
|
[anInvocation setTarget: valueClass];
|
||||||
|
|
||||||
|
// arguments are buffer pointer, length and encoding
|
||||||
[anInvocation setArgument: &bytes atIndex: 2];
|
[anInvocation setArgument: &bytes atIndex: 2];
|
||||||
[anInvocation setArgument: &length atIndex: 3];
|
[anInvocation setArgument: &length atIndex: 3];
|
||||||
[anInvocation setArgument: &encoding atIndex: 4];
|
[anInvocation setArgument: &encoding atIndex: 4];
|
||||||
|
|
||||||
|
// Let's invoke the method
|
||||||
[anInvocation invoke];
|
[anInvocation invoke];
|
||||||
|
|
||||||
|
// Get the returned value
|
||||||
|
[anInvocation getReturnValue: &value];
|
||||||
|
|
||||||
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
|
// valueFactoryMethod returns an autoreleased value
|
||||||
|
RETAIN(value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EOFactoryMethodArgumentIsNSData:
|
case EOFactoryMethodArgumentIsNSData:
|
||||||
|
// TODO: verify with WO
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1201,9 +1276,10 @@ return nexexp
|
||||||
if(!value)
|
if(!value)
|
||||||
{
|
{
|
||||||
NSData *data;
|
NSData *data;
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
|
||||||
data = AUTORELEASE([(GDL2_alloc(NSData)) initWithBytes: bytes
|
data = AUTORELEASE([(GDL2_alloc(NSData)) initWithBytes: bytes
|
||||||
length: length]);
|
length: length]);
|
||||||
|
|
||||||
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
value = [(GDL2_alloc(NSString)) initWithData: data
|
value = [(GDL2_alloc(NSString)) initWithData: data
|
||||||
encoding: encoding];
|
encoding: encoding];
|
||||||
}
|
}
|
||||||
|
@ -1217,6 +1293,8 @@ return nexexp
|
||||||
* The Adaptor calls this method during value creation
|
* The Adaptor calls this method during value creation
|
||||||
* when fetching objects from the database.
|
* when fetching objects from the database.
|
||||||
* For efficiency, the returned value is NOT autoreleased.
|
* For efficiency, the returned value is NOT autoreleased.
|
||||||
|
* Milliseconds are dropped since they cannot be easily be stored in
|
||||||
|
* NSCalendarDate.
|
||||||
**/
|
**/
|
||||||
- (NSCalendarDate *)newDateForYear: (int)year
|
- (NSCalendarDate *)newDateForYear: (int)year
|
||||||
month: (unsigned)month
|
month: (unsigned)month
|
||||||
|
@ -1228,10 +1306,12 @@ return nexexp
|
||||||
timezone: (NSTimeZone *)timezone
|
timezone: (NSTimeZone *)timezone
|
||||||
zone: (NSZone *)zone
|
zone: (NSZone *)zone
|
||||||
{
|
{
|
||||||
NSCalendarDate *date;
|
NSCalendarDate *date = nil;
|
||||||
|
|
||||||
|
// FIXME: extend initializer to include Milliseconds
|
||||||
|
|
||||||
//For efficiency reasons, the returned value is NOT autoreleased !
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
||||||
date = [[GDL2_NSCalendarDateClass allocWithZone: zone]
|
date = [(GDL2_allocWithZone(NSCalendarDate,zone))
|
||||||
initWithYear: year
|
initWithYear: year
|
||||||
month: month
|
month: month
|
||||||
day: day
|
day: day
|
||||||
|
@ -1240,8 +1320,6 @@ return nexexp
|
||||||
second: second
|
second: second
|
||||||
timeZone: timezone];
|
timeZone: timezone];
|
||||||
|
|
||||||
// TODO milliseconds ??
|
|
||||||
|
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,6 +1488,23 @@ EOAdaptorDateType Date value (attribute valueClass is kind of NSDate)
|
||||||
return _adaptorValueType;
|
return _adaptorValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the type of argument needed by the factoryMethod.
|
||||||
|
|
||||||
|
Type can be:
|
||||||
|
|
||||||
|
EOFactoryMethodArgumentIsNSData
|
||||||
|
method need one parameter: a NSData
|
||||||
|
|
||||||
|
EOFactoryMethodArgumentIsNSString
|
||||||
|
method need one parameter: a NSString
|
||||||
|
|
||||||
|
EOFactoryMethodArgumentIsBytes
|
||||||
|
method need 2 parameters (for data type valueClass): a raw bytes buffer and its length
|
||||||
|
or 3 parameters (for string type valueClass): a raw bytes buffer, its length and the encoding
|
||||||
|
|
||||||
|
See also: -valueFactoryMethod, -setFactoryMethodArgumentType:
|
||||||
|
**/
|
||||||
- (EOFactoryMethodArgumentType)factoryMethodArgumentType
|
- (EOFactoryMethodArgumentType)factoryMethodArgumentType
|
||||||
{
|
{
|
||||||
return _argumentType;
|
return _argumentType;
|
||||||
|
@ -1432,6 +1527,13 @@ See also: -setFactoryMethodArgumentType:
|
||||||
_valueFactoryMethod = NSSelectorFromString(_valueFactoryMethodName);
|
_valueFactoryMethod = NSSelectorFromString(_valueFactoryMethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set method name to use to convert value of a class
|
||||||
|
different than attribute adaptor value type.
|
||||||
|
|
||||||
|
See also: -adaptorValueByConvertingAttributeValue, -adaptorValueConversionMethod,
|
||||||
|
-adaptorValueConversionMethodName
|
||||||
|
**/
|
||||||
|
|
||||||
- (void)setAdaptorValueConversionMethodName: (NSString *)conversionMethodName
|
- (void)setAdaptorValueConversionMethodName: (NSString *)conversionMethodName
|
||||||
{
|
{
|
||||||
[self willChange];
|
[self willChange];
|
||||||
|
@ -1440,6 +1542,22 @@ See also: -setFactoryMethodArgumentType:
|
||||||
_adaptorValueConversionMethod = NSSelectorFromString(_adaptorValueConversionMethodName);
|
_adaptorValueConversionMethod = NSSelectorFromString(_adaptorValueConversionMethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the type of argument needed by the factoryMethod.
|
||||||
|
|
||||||
|
Type can be:
|
||||||
|
|
||||||
|
EOFactoryMethodArgumentIsNSData
|
||||||
|
method need one parameter: a NSData
|
||||||
|
|
||||||
|
EOFactoryMethodArgumentIsNSString
|
||||||
|
method need one parameter: a NSString
|
||||||
|
|
||||||
|
EOFactoryMethodArgumentIsBytes
|
||||||
|
method need 2 parameters (for data type valueClass): a raw bytes buffer and its length
|
||||||
|
or 3 parameters (for string type valueClass): a raw bytes buffer, its length and the encoding
|
||||||
|
|
||||||
|
See also: -setValueFactoryMethodName:, -factoryMethodArgumentType
|
||||||
|
**/
|
||||||
- (void)setFactoryMethodArgumentType: (EOFactoryMethodArgumentType)argumentType
|
- (void)setFactoryMethodArgumentType: (EOFactoryMethodArgumentType)argumentType
|
||||||
{
|
{
|
||||||
[self willChange];
|
[self willChange];
|
||||||
|
@ -1451,34 +1569,90 @@ See also: -setFactoryMethodArgumentType:
|
||||||
|
|
||||||
@implementation EOAttribute (EOAttributeValueMapping)
|
@implementation EOAttribute (EOAttributeValueMapping)
|
||||||
|
|
||||||
|
/** Validates value pointed by valueP, may set changed validated value in
|
||||||
|
valueP and return an validation exception if constraints validation fails.
|
||||||
|
valueP must not be NULL.
|
||||||
|
|
||||||
|
More details:
|
||||||
|
1. raise an exception if [self allowsNull] == NO but *valueP is nil or EONull
|
||||||
|
except if attribute is a primaryKey attribute (reason of this process
|
||||||
|
exception is currently unknown).
|
||||||
|
|
||||||
|
2. if valueClassName isn't set, return nil and leave *valueP unchanged
|
||||||
|
|
||||||
|
3. if it can't find the class by name, log message, return nil and
|
||||||
|
leave *valueP unchanged
|
||||||
|
|
||||||
|
4. do the fancy type conversions as necessary (Pretty much the current
|
||||||
|
handling we have)
|
||||||
|
|
||||||
|
5. THEN if width is not 0 call adaptorValueByConvertingAttributeValue:
|
||||||
|
on the new value and the if returned value is NSString or NSData
|
||||||
|
validate length with width and return a corresponding exception
|
||||||
|
if it's longer than allowed.
|
||||||
|
**/
|
||||||
|
|
||||||
- (NSException *)validateValue: (id*)valueP
|
- (NSException *)validateValue: (id*)valueP
|
||||||
{
|
{
|
||||||
NSException *exception=nil;
|
NSException *exception=nil;
|
||||||
|
|
||||||
NSAssert(valueP, @"No value pointer");
|
NSAssert(valueP, @"No value pointer");
|
||||||
|
|
||||||
if (*valueP == nil && [self allowsNull] == NO)
|
NSDebugMLog(@"In EOAttribute validateValue: value (class=%@) = %@ attribute = %@",
|
||||||
exception = [NSException validationExceptionWithFormat: @"attribute '%@' cannot be nil", [self name]];
|
[*valueP class],*valueP,self);
|
||||||
else if (*valueP)
|
|
||||||
{
|
|
||||||
//call self valueClassName
|
|
||||||
*valueP = [self adaptorValueByConvertingAttributeValue: *valueP];
|
|
||||||
//call attribute width
|
|
||||||
//end !
|
|
||||||
|
|
||||||
//TODO: revoir
|
// First check if value is nil or EONull
|
||||||
|
if (_isNilOrEONull(*valueP))
|
||||||
{
|
{
|
||||||
//EOEntity *entity = [self entity];
|
// Check if this is not allowed
|
||||||
//NSArray *pkAttributes = [entity primaryKeyAttributes];
|
if ([self allowsNull] == NO)
|
||||||
//TODO wowhat
|
{
|
||||||
|
NSArray *pkAttributes = [[self entity] primaryKeyAttributes];
|
||||||
|
|
||||||
if (*valueP)
|
// "Primary key attributes are ignored when enforcing allowsNull
|
||||||
|
// property for attributes. The values could be handled later
|
||||||
|
// by automatic PK-generation later
|
||||||
|
if ([pkAttributes indexOfObjectIdenticalTo: self] == NSNotFound)
|
||||||
|
{
|
||||||
|
exception =
|
||||||
|
[NSException
|
||||||
|
validationExceptionWithFormat:
|
||||||
|
@"attribute '%@' of entity '%@' cannot be nil or EONull ",
|
||||||
|
[self name],[[self entity] name]];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // There's a value.
|
||||||
|
{
|
||||||
|
NSString* valueClassName=[self valueClassName];
|
||||||
|
|
||||||
|
// if there's no valueClassName, leave the value unchanged
|
||||||
|
// and don't return an exception
|
||||||
|
|
||||||
|
if (valueClassName)
|
||||||
{
|
{
|
||||||
Class valueClass=[self _valueClass];
|
Class valueClass=[self _valueClass];
|
||||||
|
|
||||||
if ([*valueP isKindOfClass: valueClass] == NO)
|
// There's a className but no class !
|
||||||
|
if (!valueClass)
|
||||||
{
|
{
|
||||||
if ([*valueP isKindOfClass: GDL2_NSStringClass])
|
//Log this problem, leave the value unchanged
|
||||||
|
// and don't return an exception
|
||||||
|
NSLog(@"No valueClass for valueClassName '%@' in attribute %@",
|
||||||
|
valueClassName,self);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int width = 0;
|
||||||
|
IMP isKindOfClassIMP=[*valueP methodForSelector:@selector(isKindOfClass:)];
|
||||||
|
|
||||||
|
// If the value has not the good class we'll try to convert it
|
||||||
|
if ((*isKindOfClassIMP)(*valueP,@selector(isKindOfClass:),
|
||||||
|
valueClass) == NO)
|
||||||
|
{
|
||||||
|
// Is it a string ?
|
||||||
|
if ((*isKindOfClassIMP)(*valueP,@selector(isKindOfClass:),
|
||||||
|
GDL2_NSStringClass))
|
||||||
{
|
{
|
||||||
if (valueClass == GDL2_NSNumberClass)
|
if (valueClass == GDL2_NSNumberClass)
|
||||||
{
|
{
|
||||||
|
@ -1486,89 +1660,139 @@ See also: -setFactoryMethodArgumentType:
|
||||||
switch(valueTypeChar)
|
switch(valueTypeChar)
|
||||||
{
|
{
|
||||||
case 'i':
|
case 'i':
|
||||||
*valueP = [NSNumber numberWithInt:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithInt:
|
||||||
[*valueP intValue]];
|
[*valueP intValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
*valueP = [NSNumber numberWithUnsignedInt:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithUnsignedInt:
|
||||||
[*valueP unsignedIntValue]];
|
[*valueP unsignedIntValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
*valueP = [NSNumber numberWithChar:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithChar:
|
||||||
[*valueP intValue]];
|
[*valueP intValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
*valueP = [NSNumber numberWithUnsignedChar:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithUnsignedChar:
|
||||||
[*valueP unsignedIntValue]];
|
[*valueP unsignedIntValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
*valueP = [NSNumber numberWithShort:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithShort:
|
||||||
[*valueP shortValue]];
|
[*valueP shortValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
*valueP = [NSNumber numberWithUnsignedShort:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithUnsignedShort:
|
||||||
[*valueP unsignedShortValue]];
|
[*valueP unsignedShortValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
*valueP = [NSNumber numberWithLong:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithLong:
|
||||||
[*valueP longValue]];
|
[*valueP longValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
*valueP = [NSNumber numberWithUnsignedLong:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithUnsignedLong:
|
||||||
[*valueP unsignedLongValue]];
|
[*valueP unsignedLongValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
*valueP = [NSNumber numberWithLongLong:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithLongLong:
|
||||||
[*valueP longLongValue]];
|
[*valueP longLongValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
*valueP = [NSNumber numberWithUnsignedLongLong:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithUnsignedLongLong:
|
||||||
[*valueP unsignedLongLongValue]];
|
[*valueP unsignedLongLongValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
*valueP = [NSNumber numberWithFloat:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithFloat:
|
||||||
[*valueP floatValue]];
|
[*valueP floatValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*valueP = [NSNumber numberWithDouble:
|
*valueP = [GDL2_alloc(NSNumber)
|
||||||
|
initWithDouble:
|
||||||
[*valueP doubleValue]];
|
[*valueP doubleValue]];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (valueClass == GDL2_NSDecimalNumberClass)
|
else if (valueClass == GDL2_NSDecimalNumberClass)
|
||||||
*valueP = [NSDecimalNumber
|
{
|
||||||
decimalNumberWithString: *valueP];
|
*valueP = [GDL2_alloc(NSDecimalNumber)
|
||||||
|
initWithString: *valueP];
|
||||||
|
AUTORELEASE(*valueP);
|
||||||
|
}
|
||||||
else if (valueClass == GDL2_NSDataClass)
|
else if (valueClass == GDL2_NSDataClass)
|
||||||
|
{
|
||||||
|
//TODO Verify here.
|
||||||
*valueP = [*valueP
|
*valueP = [*valueP
|
||||||
dataUsingEncoding: NSASCIIStringEncoding
|
dataUsingEncoding:
|
||||||
allowLossyConversion: YES];
|
[NSString defaultCStringEncoding]];
|
||||||
|
}
|
||||||
else if (valueClass == GDL2_NSCalendarDateClass)
|
else if (valueClass == GDL2_NSCalendarDateClass)
|
||||||
|
{
|
||||||
*valueP = AUTORELEASE([(GDL2_alloc(NSCalendarDate))
|
*valueP = AUTORELEASE([(GDL2_alloc(NSCalendarDate))
|
||||||
initWithString: *valueP]);
|
initWithString: *valueP]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
};
|
||||||
{
|
|
||||||
if ([*valueP isKindOfClass: GDL2_NSStringClass])
|
|
||||||
{
|
|
||||||
unsigned width = [self width];
|
|
||||||
|
|
||||||
if (width && [*valueP length] > width)
|
// Now, test width if any
|
||||||
{
|
width = [self width];
|
||||||
const char *buf;
|
|
||||||
|
|
||||||
buf = [*valueP cString];
|
if (width>0)
|
||||||
*valueP = [NSString stringWithCString: buf
|
|
||||||
length: width];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ([*valueP isKindOfClass: GDL2_NSNumberClass])
|
|
||||||
{
|
{
|
||||||
// TODO ??
|
// First convert value to adaptor value
|
||||||
}
|
id testValue = [self adaptorValueByConvertingAttributeValue: *valueP];
|
||||||
}
|
|
||||||
|
if (testValue)
|
||||||
|
{
|
||||||
|
IMP testIsKindOfClassIMP=[testValue methodForSelector:@selector(isKindOfClass:)];
|
||||||
|
|
||||||
|
// We can test NSString and NSData type only
|
||||||
|
if ((*testIsKindOfClassIMP)(testValue,@selector(isKindOfClass:),
|
||||||
|
GDL2_NSStringClass)
|
||||||
|
|| (*testIsKindOfClassIMP)(testValue,@selector(isKindOfClass:),
|
||||||
|
GDL2_NSDataClass))
|
||||||
|
{
|
||||||
|
unsigned int testValueLength = [testValue length];
|
||||||
|
if (testValueLength > width)
|
||||||
|
{
|
||||||
|
exception = [NSException validationExceptionWithFormat:
|
||||||
|
@"Value %@ for attribute '%@' is too large",
|
||||||
|
testValue,[self name]];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ RCS_ID("$Id$")
|
||||||
#include <Foundation/NSDictionary.h>
|
#include <Foundation/NSDictionary.h>
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
#include <Foundation/NSDebug.h>
|
#include <Foundation/NSDebug.h>
|
||||||
|
#include <Foundation/NSValue.h>
|
||||||
#else
|
#else
|
||||||
#include <Foundation/Foundation.h>
|
#include <Foundation/Foundation.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -205,7 +206,7 @@ RCS_ID("$Id$")
|
||||||
NSDebugMLLog(@"gsdb", @"key=%@ intValue=%d",key,intValue);
|
NSDebugMLLog(@"gsdb", @"key=%@ intValue=%d",key,intValue);
|
||||||
NSAssert(key,@"No key");
|
NSAssert(key,@"No key");
|
||||||
|
|
||||||
[_propertyList setObject:[NSString stringWithFormat:@"%d",intValue]
|
[_propertyList setObject: [NSNumber numberWithInt: intValue]
|
||||||
forKey: key];
|
forKey: key];
|
||||||
|
|
||||||
NSDebugMLLog(@"gsdb", @"_propertyList=%@",_propertyList);
|
NSDebugMLLog(@"gsdb", @"_propertyList=%@",_propertyList);
|
||||||
|
@ -222,7 +223,7 @@ RCS_ID("$Id$")
|
||||||
NSDebugMLLog(@"gsdb", @"key=%@ yn=%s",key,(yn ? "YES" : "NO"));
|
NSDebugMLLog(@"gsdb", @"key=%@ yn=%s",key,(yn ? "YES" : "NO"));
|
||||||
NSAssert(key,@"No key");
|
NSAssert(key,@"No key");
|
||||||
|
|
||||||
[_propertyList setObject:(yn ? @"YES" : @"NO")
|
[_propertyList setObject: [NSNumber numberWithBool: yn]
|
||||||
forKey: key];
|
forKey: key];
|
||||||
|
|
||||||
NSDebugMLLog(@"gsdb", @"_propertyList=%@",_propertyList);
|
NSDebugMLLog(@"gsdb", @"_propertyList=%@",_propertyList);
|
||||||
|
|
|
@ -119,6 +119,11 @@ _isNilOrEONull(id obj)
|
||||||
(*GDL2_##CLASS_NAME##_allocWithZoneIMP) \
|
(*GDL2_##CLASS_NAME##_allocWithZoneIMP) \
|
||||||
(GDL2_##CLASS_NAME##Class,@selector(allocWithZone:),NULL)
|
(GDL2_##CLASS_NAME##Class,@selector(allocWithZone:),NULL)
|
||||||
|
|
||||||
|
// ---- +allocWithZone: ----
|
||||||
|
#define GDL2_allocWithZone(CLASS_NAME,ALLOC_ZONE) \
|
||||||
|
(*GDL2_##CLASS_NAME##_allocWithZoneIMP) \
|
||||||
|
(GDL2_##CLASS_NAME##Class,@selector(allocWithZone:),ALLOC_ZONE)
|
||||||
|
|
||||||
// ---- NSMutableString appendString: ----
|
// ---- NSMutableString appendString: ----
|
||||||
#define GDL2_AppendStringWithImp(string,methodIMP,aString) \
|
#define GDL2_AppendStringWithImp(string,methodIMP,aString) \
|
||||||
(*(methodIMP))((string),@selector(appendString:),(aString))
|
(*(methodIMP))((string),@selector(appendString:),(aString))
|
||||||
|
|
Loading…
Reference in a new issue