mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-02-23 11:41:20 +00:00
* GSWDynamicURLString.h: o remove NSMutableString protocol * GSWUtils.m o removed NSString and NSMutableString protocol use * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.gswd: o change .png to .mng * GSWExtensions.framework/GSWCollapsibleComponentContent.gswc/GSWCollapsibleComponentContent.gswd: o added framework for image * GSWeb.framework/GSWDisplayGroup.h: o aded -setQueryOperator: o added -initWithKeyValueUnarchiver: * GSWeb.framework/GSWDisplayGroup.m: o added -setQueryOperator: o unarchive queryOperator o changed hasMultipleBatches implementation * GSWeb.framework/GSWBody.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWImage.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWResourceURL.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWFrame.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWElement.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWDynamicElement.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWGenericElement.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWHTMLStaticElement.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWElementIDString.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc o removed logs * GSWeb.framework/GSWActionURL.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc o removed logs * GSWeb.framework/GSWHyperlink.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWHTMLStaticGroup.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWInput.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWText.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWTextField.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWFileUpload.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWBrowser.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWCheckBox.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWCheckBoxList.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWPopUpButton.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWRadioButton.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWRadioButtonList.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWSubmitButton.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWHiddenField.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWPasswordField.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWString.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc * GSWeb.framework/GSWImageButton.h,.m: o ivar names changes to conform to coding standards o headers changed for gsdoc git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@13471 72102866-910b-0410-8b05-ffd578937521
1045 lines
32 KiB
Objective-C
1045 lines
32 KiB
Objective-C
/* GSWAssociation.m - GSWeb: Class GSWAssociation
|
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
Written by: Manuel Guesdon <mguesdon@sbuilders.com>
|
|
Date: Jan 1999
|
|
|
|
This file is part of the GNUstep Web Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
static char rcsId[] = "$Id$";
|
|
|
|
#include <GSWeb/GSWeb.h>
|
|
#include <math.h>
|
|
#if !defined(__NetBSD__)
|
|
#include <values.h>
|
|
#endif
|
|
|
|
static NSDictionary* localMinMaxDictionary=nil;
|
|
static NSMutableDictionary* associationsHandlerClasses=nil;
|
|
static NSLock* associationsLock=nil;
|
|
static NSMutableArray* associationsLogsHandlerClasses=nil;
|
|
//====================================================================
|
|
@implementation GSWAssociation
|
|
|
|
+(void)initialize
|
|
{
|
|
if (self==[GSWAssociation class])
|
|
{
|
|
associationsLock=[NSLock new];
|
|
if (!localMinMaxDictionary)
|
|
{
|
|
localMinMaxDictionary=[[NSDictionary dictionaryWithObjectsAndKeys:
|
|
[NSNumber numberWithShort:SCHAR_MIN],@"SCHAR_MIN",
|
|
[NSNumber numberWithShort:SCHAR_MAX],@"SCHAR_MAX",
|
|
[NSNumber numberWithShort:UCHAR_MAX],@"UCHAR_MAX",
|
|
[NSNumber numberWithShort:CHAR_MIN],@"CHAR_MIN",
|
|
[NSNumber numberWithShort:CHAR_MAX],@"CHAR_MAX",
|
|
[NSNumber numberWithShort:SHRT_MIN],@"SHRT_MIN",
|
|
[NSNumber numberWithShort:SHRT_MAX],@"SHRT_MAX",
|
|
[NSNumber numberWithUnsignedInt:0],@"USHRT_MIN",
|
|
[NSNumber numberWithUnsignedInt:USHRT_MAX],@"USHRT_MAX",
|
|
[NSNumber numberWithInt:INT_MIN],@"INT_MIN",
|
|
[NSNumber numberWithInt:INT_MAX],@"INT_MAX",
|
|
[NSNumber numberWithUnsignedInt:0],@"UINT_MIN",
|
|
[NSNumber numberWithUnsignedInt:UINT_MAX],@"UINT_MAX",
|
|
[NSNumber numberWithLong:LONG_MIN],@"LONG_MIN",
|
|
[NSNumber numberWithLong:LONG_MAX],@"LONG_MAX",
|
|
[NSNumber numberWithUnsignedLong:0],@"ULONG_MIN",
|
|
[NSNumber numberWithUnsignedLong:ULONG_MAX],@"ULONG_MAX",
|
|
#ifdef LONG_LONG_MAX
|
|
|
|
[NSNumber numberWithLongLong:LONG_LONG_MIN],@"LONG_LONG_MIN",
|
|
[NSNumber numberWithLongLong:LONG_LONG_MAX],@"LONG_LONG_MAX",
|
|
#endif
|
|
#ifdef ULONG_LONG_MAX
|
|
[NSNumber numberWithUnsignedLongLong:0],@"ULONG_LONG_MIN",
|
|
[NSNumber numberWithUnsignedLongLong:ULONG_LONG_MAX],@"ULONG_LONG_MAX",
|
|
#endif
|
|
[NSNumber numberWithFloat:FLT_MIN],@"FLOAT_MIN",
|
|
[NSNumber numberWithFloat:FLT_MAX],@"FLOAT_MAX",
|
|
[NSNumber numberWithFloat:DBL_MIN],@"DOUBLE_MIN",
|
|
[NSNumber numberWithFloat:DBL_MAX],@"DOUBLE_MAX",
|
|
nil,nil]
|
|
retain];
|
|
};
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(void)dealloc
|
|
{
|
|
DESTROY(localMinMaxDictionary);
|
|
DESTROY(associationsHandlerClasses);
|
|
DESTROY(associationsLogsHandlerClasses);
|
|
DESTROY(associationsLock);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// init
|
|
-(id)init
|
|
{
|
|
if ((self=[super init]))
|
|
{
|
|
};
|
|
return self;
|
|
};
|
|
|
|
-(void)dealloc
|
|
{
|
|
DESTROY(bindingName);
|
|
DESTROY(declarationName);
|
|
DESTROY(declarationType);
|
|
[super dealloc];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(id)copyWithZone:(NSZone*)zone;
|
|
{
|
|
GSWAssociation* clone = [[isa allocWithZone:zone] init];
|
|
clone->debugEnabled=debugEnabled;
|
|
[clone setDebugEnabledForBinding:bindingName
|
|
declarationName:declarationName
|
|
declarationType:declarationType];
|
|
return clone;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)description
|
|
{
|
|
GSWLogAssertGood(self);
|
|
LOGObjectFnNotImplemented(); //TODOFN
|
|
return [super description];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)bindingName
|
|
{
|
|
return bindingName;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)declarationName
|
|
{
|
|
return declarationName;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)declarationType
|
|
{
|
|
return declarationType;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// isValueConstant
|
|
|
|
-(BOOL)isValueConstant
|
|
{
|
|
//OK
|
|
[self subclassResponsibility:_cmd];
|
|
return NO;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// isValueSettable
|
|
|
|
- (BOOL)isValueSettable
|
|
{
|
|
//OK
|
|
[self subclassResponsibility:_cmd];
|
|
return NO;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// setValue:inObject:
|
|
//NDFN
|
|
-(void)setValue:(id)value_
|
|
inObject:(id)object_
|
|
{
|
|
//OK
|
|
[self subclassResponsibility:_cmd];
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// setValue:inComponent:
|
|
|
|
-(void)setValue:(id)value_
|
|
inComponent:(GSWComponent*)component_
|
|
{
|
|
//OK
|
|
[self setValue:value_
|
|
inObject:component_];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// valueInObject:
|
|
//NDFN
|
|
-(id)valueInObject:(id)object_
|
|
{
|
|
//OK
|
|
return [self subclassResponsibility:_cmd];
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// valueInComponent:
|
|
|
|
-(id)valueInComponent:(GSWComponent*)component_;
|
|
{
|
|
//OK
|
|
return [self valueInObject:component_];
|
|
};
|
|
|
|
|
|
@end
|
|
|
|
//====================================================================
|
|
@implementation GSWAssociation (GSWAssociationCreation)
|
|
//--------------------------------------------------------------------
|
|
// associationWithKeyPath:
|
|
|
|
+(GSWAssociation*)associationWithKeyPath:(NSString*)keyPath_
|
|
{
|
|
//OK
|
|
if (keyPath_)
|
|
{
|
|
if ([keyPath_ hasPrefix:@"^"]
|
|
|| (!WOStrictFlag && [keyPath_ hasPrefix:@"~"]))
|
|
return [[[GSWBindingNameAssociation alloc]initWithKeyPath:keyPath_] autorelease];
|
|
else
|
|
return [[[GSWKeyValueAssociation alloc]initWithKeyPath:keyPath_] autorelease];
|
|
}
|
|
else
|
|
return nil;
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// associationWithValue:
|
|
|
|
+(GSWAssociation*)associationWithValue:(id)value_
|
|
{
|
|
//OK
|
|
return [[[GSWConstantValueAssociation alloc]initWithValue:value_] autorelease];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// associationFromString:
|
|
//NDFN
|
|
+(GSWAssociation*)associationFromString:(NSString*)string_
|
|
{
|
|
GSWAssociation* _assoc=nil;
|
|
LOGClassFnStart();
|
|
NSDebugMLLog(@"associations",@"string_=[%@]",string_);
|
|
if ([string_ length]<=0)
|
|
_assoc=[self associationWithValue:string_];
|
|
else
|
|
{
|
|
NSString* _trimmedString=[string_ stringByTrimmingSpaces];
|
|
if ([_trimmedString isEqualToString:NSTYES])
|
|
{
|
|
_assoc=[self associationWithValue:[NSNumber numberWithBool:YES]];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else if ([_trimmedString isEqualToString:NSTNO])
|
|
{
|
|
_assoc=[self associationWithValue:[NSNumber numberWithBool:NO]];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else if ([_trimmedString hasPrefix:@"^"])
|
|
{
|
|
_assoc=[self associationWithKeyPath:_trimmedString];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else if ([_trimmedString hasPrefix:@"\""])
|
|
{
|
|
if ([_trimmedString hasSuffix:@"\""])
|
|
{
|
|
_assoc=[self associationWithValue:[[_trimmedString stringWithoutPrefix:@"\""] stringWithoutSuffix:@"\""]];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else
|
|
{
|
|
ExceptionRaise(@"GSWAssociation",@"String '%@' start with a \" but doesn't finish with a \"",
|
|
_trimmedString);
|
|
};
|
|
}
|
|
else if ([_trimmedString hasPrefix:@"\'"])
|
|
{
|
|
if ([_trimmedString hasSuffix:@"\'"])
|
|
{
|
|
_assoc=[self associationWithValue:[[_trimmedString stringWithoutPrefix:@"\'"] stringWithoutSuffix:@"\'"]];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else
|
|
{
|
|
ExceptionRaise(@"GSWAssociation",@"String '%@' start with a character ' but doesn't finish with a character '",
|
|
_trimmedString);
|
|
};
|
|
}
|
|
else if ([_trimmedString hasPrefix:@"#"])
|
|
{
|
|
NSString* _numberString=[_trimmedString stringWithoutPrefix:@"#"];
|
|
//char* cString=[_numberString lossyCString];//TODO
|
|
char* cString=[_numberString cString];//TODO
|
|
char* endPtr=NULL;
|
|
int _value=strtol(cString,&endPtr,16);
|
|
NSDebugMLLog(@"associations",@"_value=[%d]",_value);
|
|
if (endPtr && *endPtr)
|
|
{
|
|
ExceptionRaise(@"GSWAssociation",@"String '%@' start with a '#' but doesn't countain an hexadecimal number (on %dth Character)",
|
|
_trimmedString,
|
|
(int)(endPtr-cString+1));
|
|
};
|
|
_assoc=[self associationWithValue:[NSNumber numberWithInt:_value]];
|
|
}
|
|
else
|
|
{
|
|
NSNumber*_limit=[localMinMaxDictionary objectForKey:_trimmedString];
|
|
NSDebugMLLog(@"associations",@"_limit=[%@]",_limit);
|
|
if (_limit)
|
|
{
|
|
_assoc=[self associationWithValue:_limit];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else
|
|
{
|
|
NSCharacterSet* _cset=[NSCharacterSet characterSetWithCharactersInString:@"-+0123456789"];
|
|
NSRange _firstCharRange=[_trimmedString rangeOfCharacterFromSet:_cset
|
|
options:0
|
|
range:NSMakeRange(0,1)];
|
|
NSDebugMLLog(@"associations",@"_firstCharRange.length=%d _firstCharRange.location=%d ",_firstCharRange.length,_firstCharRange.location);
|
|
if (_firstCharRange.length==0 || _firstCharRange.location!=0)
|
|
{
|
|
_assoc=[self associationWithKeyPath:_trimmedString];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
}
|
|
else
|
|
{
|
|
//char* cString=[_trimmedString lossyCString];//TODO
|
|
char* cString=[_trimmedString cString];//TODO
|
|
char* endPtr=NULL;
|
|
int _value=strtol(cString,&endPtr,10);
|
|
NSDebugMLLog(@"associations",@"_value=[%d]",_value);
|
|
if (endPtr && *endPtr)
|
|
{
|
|
NSDebugMLLog(@"associations",@"endPtr=[%s]",endPtr);
|
|
NSDebugMLLog(@"associations",@"_value=[%d]",_value);
|
|
ExceptionRaise(@"GSWAssociation",
|
|
@"String '%@' must be a good number",
|
|
_trimmedString);
|
|
};
|
|
_assoc=[self associationWithValue:[NSNumber numberWithInt:_value]];
|
|
NSDebugMLLog(@"associations",@"_assoc=[%@]",_assoc);
|
|
};
|
|
};
|
|
};
|
|
};
|
|
LOGClassFnStop();
|
|
return _assoc;
|
|
};
|
|
|
|
//====================================================================
|
|
@implementation GSWAssociation (GSWAssociationHandlers)
|
|
//--------------------------------------------------------------------
|
|
+(void)setClasse:(Class)class_
|
|
forHandler:(NSString*)handler_
|
|
{
|
|
LOGClassFnStart();
|
|
NSDebugMLLog(@"associations",@"class_=%@",class_);
|
|
NSDebugMLLog(@"associations",@"handler_=%@",handler_);
|
|
TmpLockBeforeDate(associationsLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
|
|
if (!associationsHandlerClasses)
|
|
{
|
|
if (class_)
|
|
associationsHandlerClasses=[NSMutableDictionary new];
|
|
};
|
|
if (class_)
|
|
[associationsHandlerClasses setObject:class_
|
|
forKey:handler_];
|
|
else if (associationsHandlerClasses)
|
|
[associationsHandlerClasses removeObjectForKey:handler_];
|
|
TmpUnlock(associationsLock);
|
|
LOGClassFnStop();
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(void)addLogHandlerClasse:(Class)class_
|
|
{
|
|
LOGClassFnStart();
|
|
NSDebugMLLog(@"associations",@"class_=%@",class_);
|
|
TmpLockBeforeDate(associationsLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
|
|
if (!associationsLogsHandlerClasses)
|
|
{
|
|
if (class_)
|
|
associationsLogsHandlerClasses=[NSMutableArray new];
|
|
};
|
|
if (class_)
|
|
[associationsLogsHandlerClasses addObject:class_];
|
|
TmpUnlock(associationsLock);
|
|
LOGClassFnStop();
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(void)removeLogHandlerClasse:(Class)class_
|
|
{
|
|
LOGClassFnStart();
|
|
NSDebugMLLog(@"associations",@"class_=%@",class_);
|
|
TmpLockBeforeDate(associationsLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
|
|
if (associationsHandlerClasses)
|
|
{
|
|
if (class_)
|
|
[associationsLogsHandlerClasses removeObject:class_];
|
|
};
|
|
TmpUnlock(associationsLock);
|
|
LOGClassFnStop();
|
|
};
|
|
|
|
@end
|
|
/*
|
|
//====================================================================
|
|
@implementation GSWAssociation (GSWAssociationOldFn)
|
|
//--------------------------------------------------------------------
|
|
// value
|
|
|
|
-(id)value
|
|
{
|
|
//OK
|
|
GSWContext* context=[[GSWApplication application] context];
|
|
id object=[context component];
|
|
[self valueInComponent:object];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// setValue:inComponent:
|
|
//OldFn
|
|
-(void)setValue:(id)value_
|
|
{
|
|
//OK
|
|
GSWContext* context=[[GSWApplication application] context];
|
|
id object=[context component];
|
|
[self setValue:(id)value_
|
|
inComponent:object];
|
|
};
|
|
@end
|
|
*/
|
|
//====================================================================
|
|
@implementation GSWAssociation (GSWAssociationA)
|
|
|
|
//--------------------------------------------------------------------
|
|
-(BOOL)isImplementedForComponent:(NSObject*)component_
|
|
{
|
|
//OK
|
|
[self subclassResponsibility:_cmd];
|
|
return NO;
|
|
};
|
|
|
|
@end
|
|
|
|
//====================================================================
|
|
@implementation GSWAssociation (GSWAssociationB)
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)keyPath
|
|
{
|
|
//OK
|
|
[self subclassResponsibility:_cmd];
|
|
return nil;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)logValue:(id)value_
|
|
forSet:(BOOL)set_
|
|
{
|
|
if (debugEnabled)
|
|
{
|
|
if (associationsLogsHandlerClasses)
|
|
{
|
|
TmpLockBeforeDate(associationsLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
|
|
NS_DURING
|
|
{
|
|
int i=0;
|
|
Class _class=Nil;
|
|
int _handlerCount=[associationsLogsHandlerClasses count];
|
|
NSString* _debugDescription=[self debugDescription];
|
|
for(i=0;i<_handlerCount;i++)
|
|
{
|
|
_class=[associationsLogsHandlerClasses objectAtIndex:i];
|
|
if (set_)
|
|
[_class logSetValueForDeclarationNamed:declarationName
|
|
type:declarationType
|
|
bindingNamed:bindingName
|
|
associationDescription:_debugDescription
|
|
value:value_];
|
|
else
|
|
[_class logTakeValueForDeclarationNamed:declarationName
|
|
type:declarationType
|
|
bindingNamed:bindingName
|
|
associationDescription:_debugDescription
|
|
value:value_];
|
|
};
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGException(@"%@ (%@)",localException,[localException reason]);
|
|
TmpUnlock(associationsLock);
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
TmpUnlock(associationsLock);
|
|
};
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)logTakeValue:(id)value_
|
|
{
|
|
[self logValue:value_
|
|
forSet:NO];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)logSetValue:(id)value_
|
|
{
|
|
[self logValue:value_
|
|
forSet:YES];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)logSynchronizeForValue:(id)value_
|
|
inComponent:(NSObject*)component_
|
|
componentToParent:(BOOL)componentToParent_
|
|
{
|
|
if (associationsHandlerClasses)
|
|
{
|
|
TmpLockBeforeDate(associationsLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
|
|
NS_DURING
|
|
{
|
|
int i=0;
|
|
Class _class=Nil;
|
|
int _handlerCount=[associationsLogsHandlerClasses count];
|
|
NSString* _debugDescription=[self debugDescription];
|
|
for(i=0;i<_handlerCount;i++)
|
|
{
|
|
_class=[associationsLogsHandlerClasses objectAtIndex:i];
|
|
if (componentToParent_)
|
|
[_class logSynchronizeComponentToParentForValue:value_
|
|
association:self
|
|
inComponent:component_];
|
|
else
|
|
[_class logSynchronizeParentToComponentForValue:value_
|
|
association:self
|
|
inComponent:component_];
|
|
};
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGException(@"%@ (%@)",localException,[localException reason]);
|
|
TmpUnlock(associationsLock);
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
TmpUnlock(associationsLock);
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)logSynchronizeComponentToParentForValue:(id)value_
|
|
inComponent:(NSObject*)component_
|
|
{
|
|
[self logSynchronizeForValue:value_
|
|
inComponent:component_
|
|
componentToParent:YES];
|
|
};
|
|
//--------------------------------------------------------------------
|
|
-(void)logSynchronizeParentToComponentForValue:(id)value_
|
|
inComponent:(NSObject*)component_
|
|
{
|
|
[self logSynchronizeForValue:value_
|
|
inComponent:component_
|
|
componentToParent:NO];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)debugDescription
|
|
{
|
|
//OK
|
|
[self subclassResponsibility:_cmd];
|
|
return nil;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)setDebugEnabledForBinding:(NSString*)bindingName_
|
|
declarationName:(NSString*)declarationName_
|
|
declarationType:(NSString*)declarationType_
|
|
{
|
|
debugEnabled=YES;
|
|
ASSIGN(bindingName,bindingName_);
|
|
ASSIGN(declarationName,declarationName_);
|
|
ASSIGN(declarationType,declarationType_);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(id)valueInObject:(id)object_
|
|
forKeyPath:(NSString*)keyPath_
|
|
{
|
|
id retValue=nil;
|
|
#ifdef GDL2
|
|
id EONullNull=[EONull null];
|
|
#else
|
|
id EONullNull=[NSNull null];
|
|
#endif
|
|
LOGClassFnStart();
|
|
NSDebugMLLog(@"associations",@"GSWAssociation: keyPath_=%@ object_=%p (class: %@)",
|
|
keyPath_,object_,[object_ class]);
|
|
if (keyPath_ && object_ && object_!=EONullNull)
|
|
{
|
|
#if GDL2
|
|
NS_DURING
|
|
{
|
|
retValue=[object_ valueForKeyPath:keyPath_];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
NSLog(@"Attempt to get %@ -%@ raised an exception (%@)",
|
|
[object_ class],
|
|
keyPath_,
|
|
localException);
|
|
localException = [localException exceptionByAddingToUserInfoKey:@"Invalid Ivars/Methods"
|
|
format:@"-[%@ %@]",
|
|
[object_ class],
|
|
keyPath_];
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
if (retValue==EONullNull)
|
|
retValue=nil;
|
|
#else
|
|
NSMutableArray* keys=[[keyPath_ componentsSeparatedByString:@"."] mutableCopy];
|
|
id _part=nil;
|
|
Class _handlerClass=Nil;
|
|
retValue=object_;
|
|
NSAssert(retValue,@"No Component");
|
|
while(retValue && [keys count]>0)
|
|
{
|
|
_part=[keys objectAtIndex:0];
|
|
[keys removeObjectAtIndex:0];
|
|
if (retValue) {
|
|
NSDebugMLLog(@"associations",@"object_get_class_name(retValue object)=%s", object_get_class_name(retValue));
|
|
}
|
|
NSDebugMLLog(@"associations",@"_part=%@",_part);
|
|
NSDebugMLLog(@"associations",@"_part class=%@",NSStringFromClass([_part class]));
|
|
if ([_part hasPrefix:@"\""])
|
|
{
|
|
_part=[_part stringWithoutPrefix:@"\""];
|
|
while([keys count]>0)
|
|
{
|
|
id tmpPart=[keys objectAtIndex:0];
|
|
[keys removeObjectAtIndex:0];
|
|
if ([tmpPart hasSuffix:@"\""])
|
|
{
|
|
tmpPart=[tmpPart stringWithoutSuffix:@"\""];
|
|
_part=[_part stringByAppendingFormat:@".%@",tmpPart];
|
|
break;
|
|
}
|
|
else
|
|
_part=[_part stringByAppendingFormat:@".%@",tmpPart];
|
|
}
|
|
}
|
|
NSDebugMLLog(@"associations",@"_part=%@",_part);
|
|
_handlerClass=[associationsHandlerClasses objectForKey:_part];
|
|
NSDebugMLLog(@"associations",@"_handlerClass=%@",_handlerClass);
|
|
if (_handlerClass)
|
|
retValue=[_handlerClass processValueInObject:retValue
|
|
forHandler:_part
|
|
forKeyPath:keys];
|
|
else if ([_part isEqualToString:GSASK_Class])
|
|
{
|
|
Class _class=Nil;
|
|
NSAssert2([keys count]>0,@"No class name for handler %@ in %@",
|
|
GSASK_Class,
|
|
keyPath_);
|
|
_part=[keys objectAtIndex:0];
|
|
[keys removeObjectAtIndex:0];
|
|
NSDebugMLLog(@"associations",@"_part=%@",_part);
|
|
_class=NSClassFromString(_part);
|
|
NSAssert3(_class>0,@"No class named %@ for handler %@ in %@",
|
|
_part,
|
|
GSASK_Class,
|
|
keyPath_);
|
|
if (_class)
|
|
retValue=_class;
|
|
else
|
|
retValue=nil;
|
|
}
|
|
else if ([_part isEqualToString:GSASK_Language])
|
|
{
|
|
NSArray* languages=[[GSWApp _context] languages];
|
|
int count=[languages count];
|
|
id v=nil;
|
|
int i=0;
|
|
for(i=0;!v && i<count;i++)
|
|
{
|
|
id language=[languages objectAtIndex:i];
|
|
//MGNEW v=[retValue getIVarNamed:language];
|
|
v=[retValue valueForKey:language];
|
|
};
|
|
retValue=v;
|
|
}
|
|
else
|
|
{
|
|
BOOL skipping = NO;
|
|
NSDebugMLLog(@"associations",@"call %@ valueForKey:%@",
|
|
[retValue class],
|
|
_part);
|
|
NS_DURING
|
|
{
|
|
//MGNEW retValue=[retValue getIVarNamed:_part];
|
|
retValue=[retValue valueForKey:_part];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
NSLog(@"Attempt to get %@ -%@ raised an exception (%@)",
|
|
[retValue class],
|
|
_part,
|
|
localException);
|
|
localException = [localException exceptionByAddingToUserInfoKey:@"Invalid Ivars/Methods" format:@"-[%@ %@]",[retValue class],_part];
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
};
|
|
if (retValue==EONullNull)
|
|
retValue=nil;
|
|
};
|
|
#endif
|
|
};
|
|
if (retValue)
|
|
{
|
|
NSDebugMLLog(@"associations",@"retValue=%@",retValue);
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLLog(@"associations",@"retValue=nil");
|
|
}
|
|
LOGClassFnStop();
|
|
return retValue;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(void)setValue:(id)value_
|
|
inObject:(id)object_
|
|
forKeyPath:(NSString*)keyPath_
|
|
{
|
|
LOGClassFnStart();
|
|
NSDebugMLLog(@"associations",@"GSWAssociation: setValue:%@",value_);
|
|
NSDebugMLLog(@"associations",@"value_ class:%@",[value_ class]);
|
|
NSDebugMLLog(@"associations",@"value_ String class:%@",NSStringFromClass([value_ class]));
|
|
NSDebugMLLog(@"associations",@"object_ String class:%@",NSStringFromClass([object_ class]));
|
|
NSDebugMLLog(@"associations",@"GSWAssociation: keyPath_:%@",keyPath_);
|
|
if (keyPath_)
|
|
{
|
|
#if GDL2
|
|
[object_ takeValue:value_
|
|
forKeyPath:keyPath_];
|
|
#else
|
|
NSMutableArray* keys=[[keyPath_ componentsSeparatedByString:@"."] mutableCopy];
|
|
id _part=nil;
|
|
id _object=object_;
|
|
Class _handlerClass=Nil;
|
|
NSAssert(_object,@"No Object");
|
|
while(_object && [keys count]>0)
|
|
{
|
|
_part=[keys objectAtIndex:0];
|
|
[keys removeObjectAtIndex:0];
|
|
NSDebugMLLog(@"associations",@"_part=%@",_part);
|
|
NSDebugMLLog(@"associations",@"_part class=%@",NSStringFromClass([_part class]));
|
|
if ([_part hasPrefix:@"\""])
|
|
{
|
|
_part=[_part stringWithoutPrefix:@"\""];
|
|
while([keys count]>0)
|
|
{
|
|
id tmpPart=[keys objectAtIndex:0];
|
|
[keys removeObjectAtIndex:0];
|
|
if ([tmpPart hasSuffix:@"\""])
|
|
{
|
|
tmpPart=[tmpPart stringWithoutSuffix:@"\""];
|
|
_part=[_part stringByAppendingFormat:@".%@",tmpPart];
|
|
break;
|
|
}
|
|
else
|
|
_part=[_part stringByAppendingFormat:@".%@",tmpPart];
|
|
}
|
|
}
|
|
NSDebugMLLog(@"associations",@"_part=%@",_part);
|
|
|
|
_handlerClass=[associationsHandlerClasses objectForKey:_part];
|
|
NSDebugMLLog(@"associations",@"_handlerClass=%@",_handlerClass);
|
|
if (_handlerClass)
|
|
{
|
|
_object=[_handlerClass processSetValue:value_
|
|
inObject:_object
|
|
forHandler:_part
|
|
forKeyPath:keys];
|
|
}
|
|
else
|
|
{
|
|
if ([keys count]>0)
|
|
{
|
|
if ([_part isEqualToString:GSASK_Class])
|
|
{
|
|
Class _class=Nil;
|
|
|
|
NSAssert2([keys count]>0,@"No class name for handler %@ in %@",
|
|
GSASK_Class,
|
|
keyPath_);
|
|
_part=[keys objectAtIndex:0];
|
|
[keys removeObjectAtIndex:0];
|
|
NSDebugMLLog(@"associations",@"_part=%@",_part);
|
|
_class=NSClassFromString(_part);
|
|
NSAssert3(_class>0,@"No class named %@ for handler %@ in %@",
|
|
_part,
|
|
GSASK_Class,
|
|
keyPath_);
|
|
if (_class)
|
|
_object=_class;
|
|
else
|
|
_object=nil;
|
|
}
|
|
else {
|
|
//MGNEW _object=[_object getIVarNamed:_part];
|
|
_object=[_object valueForKey:_part];//MGNEW
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GSWLogAssertGood(_object);
|
|
//MGNEW [_object setIVarNamed:_part
|
|
// withValue:value_];
|
|
[_object takeValue:value_
|
|
forKey:_part];//MGNEW
|
|
#ifdef GDL2
|
|
NSDebugMLLog(@"associations",@"object_ class=%@",[object_ class]);
|
|
NSDebugMLLog(@"associations",@"_object class=%@",[_object class]);
|
|
// Turbocat
|
|
if (_object && [_object isKindOfClass:[GSWComponent class]]) {
|
|
NSException* _exp = [_object validateValue:&value_ forKey:_part];
|
|
|
|
if (_exp) {
|
|
NSException* _exception=nil;
|
|
|
|
_exception=[NSException exceptionWithName:@"EOValidationException"
|
|
reason:[_exp reason]
|
|
userInfo:[NSDictionary
|
|
dictionaryWithObjectsAndKeys:
|
|
(value_ ? value_ : @"nil"),@"EOValidatedObjectUserInfoKey",
|
|
keyPath_,@"EOValidatedPropertyUserInfoKey",
|
|
nil,nil]];
|
|
[object_ validationFailedWithException:_exception
|
|
value:value_
|
|
keyPath:keyPath_];
|
|
}
|
|
}
|
|
#endif
|
|
_object=nil;
|
|
};
|
|
};
|
|
};
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLLog(@"associations",@"GSWAssociation: setValue:%@ : NoKeyPath",value_);
|
|
};
|
|
LOGClassFnStop();
|
|
};
|
|
|
|
@end
|
|
|
|
//===================================================================================
|
|
@implementation NSDictionary (GSWAssociation)
|
|
|
|
-(BOOL)isAssociationDebugEnabledInComponent:(NSObject*)component_
|
|
{
|
|
BOOL _debug=NO;
|
|
GSWAssociation* _debugAssociation=[self objectForKey:@"GSWDebug"];
|
|
if (_debugAssociation)
|
|
{
|
|
id _value=[_debugAssociation valueInObject:component_];
|
|
_debug=boolValueWithDefaultFor(_value,NO);
|
|
};
|
|
return _debug;
|
|
};
|
|
|
|
-(void)associationsSetDebugEnabled
|
|
{
|
|
NSEnumerator* enumerator=nil;
|
|
id _key=nil;
|
|
id _asociation=nil;
|
|
LOGObjectFnStart();
|
|
enumerator = [self keyEnumerator];
|
|
while ((_key = [enumerator nextObject]))
|
|
{
|
|
NSDebugMLLog(@"associations",@"_key=%@",_key);
|
|
_asociation=[self objectForKey:_key];
|
|
[_asociation setDebugEnabledForBinding:@""
|
|
declarationName:_key
|
|
declarationType:@""]; //TODO
|
|
};
|
|
LOGObjectFnStop();
|
|
};
|
|
|
|
-(void)associationsSetValuesFromObject:(id)from
|
|
inObject:(id)to
|
|
{
|
|
NSEnumerator *enumerator = nil;
|
|
id key=nil;
|
|
id varValue=nil;
|
|
id var=nil;
|
|
LOGObjectFnStart();
|
|
NSDebugMLLog(@"associations",@"from=%@",from);
|
|
NSDebugMLLog(@"associations",@"to=%@",to);
|
|
enumerator = [self keyEnumerator];
|
|
while ((key = [enumerator nextObject]))
|
|
{
|
|
NSDebugMLLog(@"associations",@"key=%@",key);
|
|
/* NSAssert2([key isKindOfClass:[GSWAssociation class]],
|
|
@"key is not an GSWAssociation but a %@: %@",
|
|
[key class],
|
|
key);*/
|
|
var=[self objectForKey:key];
|
|
NSDebugMLLog(@"associations",@"var=%@",var);
|
|
/* NSAssert2([var isKindOfClass:[GSWAssociation class]],
|
|
@"Variable is not an GSWAssociation but a %@: %@",
|
|
[var class],
|
|
var);*/
|
|
if ([var isKindOfClass:[GSWAssociation class]])
|
|
varValue=[var valueInComponent:from];
|
|
else
|
|
varValue=var;
|
|
NSDebugMLLog(@"associations",@"varValue=%@",varValue);
|
|
if (![key isKindOfClass:[GSWAssociation class]])
|
|
key=[GSWAssociation associationWithKeyPath:key];
|
|
[key setValue:varValue
|
|
inComponent:to];
|
|
};
|
|
LOGObjectFnStop();
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSDictionary*)associationsWithoutPrefix:(NSString*)prefix_
|
|
removeFrom:(NSMutableDictionary*)removeFrom_
|
|
{
|
|
NSMutableDictionary* _newAssociation=nil;
|
|
NSEnumerator *enumerator = nil;
|
|
id _key=nil;
|
|
id _varKey=nil;
|
|
id _varKeyAssociation=nil;
|
|
id _value=nil;
|
|
LOGObjectFnStart();
|
|
_newAssociation=(NSMutableDictionary*)[NSMutableDictionary dictionary];
|
|
enumerator = [self keyEnumerator];
|
|
while ((_key = [enumerator nextObject]))
|
|
{
|
|
NSDebugMLLog(@"associations",@"_key=%@",_key);
|
|
if ([_key hasPrefix:prefix_])
|
|
{
|
|
[removeFrom_ removeObjectForKey:_key];
|
|
_value=[self objectForKey:_key];
|
|
NSDebugMLLog(@"associations",@"_value=%@",_value);
|
|
_varKey=[_key stringWithoutPrefix:prefix_];
|
|
NSDebugMLLog(@"associations",@"_varKey=%@",_varKey);
|
|
_varKeyAssociation=[GSWAssociation associationWithKeyPath:_varKey];
|
|
NSDebugMLLog(@"associations",@"_varKeyAssociation=%@",_varKeyAssociation);
|
|
[_newAssociation setObject:_value
|
|
forKey:_varKeyAssociation];
|
|
};
|
|
};
|
|
_newAssociation=[NSDictionary dictionaryWithDictionary:_newAssociation];
|
|
LOGObjectFnStop();
|
|
return _newAssociation;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSDictionary*)dictionaryByReplacingStringsWithAssociations
|
|
{
|
|
NSMutableDictionary* _newDictionary=[NSMutableDictionary dictionary];
|
|
NSEnumerator* _enum=[self keyEnumerator];
|
|
id _key=nil;
|
|
id _value=nil;
|
|
id _newValue=nil;
|
|
while ((_key=[_enum nextObject]))
|
|
{
|
|
_value=[self objectForKey:_key];
|
|
NSDebugMLog(@"_key=%@ _value=%@",_key,_value);
|
|
if ([_value isKindOfClass:[NSString class]])
|
|
{
|
|
_newValue=[GSWAssociation associationFromString:_value];
|
|
NSAssert(_newValue,@"Nil value");
|
|
}
|
|
else if ([_value isKindOfClass:[NSArray class]])
|
|
{
|
|
_newValue=[_value arrayByReplacingStringsWithAssociations];
|
|
NSAssert(_newValue,@"Nil value");
|
|
}
|
|
else if ([_value isKindOfClass:[NSDictionary class]])
|
|
{
|
|
_newValue=[_value dictionaryByReplacingStringsWithAssociations];
|
|
NSAssert(_newValue,@"Nil value");
|
|
}
|
|
else
|
|
_newValue=_value;
|
|
[_newDictionary setObject:_newValue
|
|
forKey:_key];
|
|
};
|
|
return [NSDictionary dictionaryWithDictionary:_newDictionary];
|
|
};
|
|
|
|
@end
|
|
|
|
//===================================================================================
|
|
@implementation NSArray (GSWAssociation)
|
|
-(NSArray*)arrayByReplacingStringsWithAssociations
|
|
{
|
|
NSMutableArray* _newArray=[NSMutableArray array];
|
|
int _count=[self count];
|
|
int i=0;
|
|
id _value=nil;
|
|
id _newValue=nil;
|
|
for(i=0;i<_count;i++)
|
|
{
|
|
_value=[self objectAtIndex:i];
|
|
NSDebugMLog(@"i=%d _value=%@",i,_value);
|
|
if ([_value isKindOfClass:[NSString class]])
|
|
{
|
|
_newValue=[GSWAssociation associationFromString:_value];
|
|
}
|
|
else if ([_value isKindOfClass:[NSArray class]])
|
|
{
|
|
_newValue=[_value arrayByReplacingStringsWithAssociations];
|
|
}
|
|
else if ([_value isKindOfClass:[NSDictionary class]])
|
|
{
|
|
_newValue=[_value dictionaryByReplacingStringsWithAssociations];
|
|
}
|
|
else
|
|
_newValue=_value;
|
|
[_newArray addObject:_newValue];
|
|
};
|
|
return [NSArray arrayWithArray:_newArray];
|
|
};
|
|
@end
|