libs-gsweb/GSWeb.framework/GSWAssociation.m
mguesdon 6a4d7eeb1d 2001-03-11 Manuel Guesdon <mguesdon@orange-concept.com>
* GSWeb.framework/GSWWOCompatibility.h/.m: added
        * GSWeb.framework/GNUmakefile: added GSWWOCompatibility.h/.m
        * GSWeb.framework/GSWApplication.h/m: added WOApplicationMain, handle WO/GSWeb names
        * GSWeb.framework/GSWContext.m: handle WO/GSWeb names, added traces
        * GSWeb.framework/GSWConstants.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDynamicURLString.m: handle WO/GSWeb names
        * GSWeb.framework/GSWProjectBundle.m/.h: handle WO/GSWeb names, suppress warnings
        * GSWeb.framework/GSWSession.m: handle WO/GSWeb names
        * GSWeb.framework/GSWRequest.m: handle WO/GSWeb names
        * GSWeb.framework/GSWTemplateParser.m: handle WO/GSWeb names,
                added tag counts to help errors hunt
        * GSWeb.framework/GSWBundle.m: handle WO/GSWeb names, added traces
        * GSWeb.framework/GSWResourceManager.m: handle WO/GSWeb names
        * GSWeb.framework/GSWURLValuedElementData.m: handle WO/GSWeb names
        * GSWeb.framework/GSWComponentRequestHandler.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDirectAction.m: handle WO/GSWeb names
        * GSWeb.framework/GSWForm.m/.h: handle WO/GSWeb names
        * GSWeb.framework/GSWHyperlink.m/.h: handle WO/GSWeb names
        * GSWeb.framework/GSWResourceRequestHandler.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDirectActionRequestHandler.m: handle WO/GSWeb names
        * GSWeb.framework/GSWActiveImage.m/.h: handle WO/GSWeb names
        * GSWeb.framework/GSWBindingNameAssociation.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWBrowser.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWComponent.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWHTMLURLValuedElement.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWImageButton.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWInput.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWPopUpButton.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWString.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWAssociation.m: handle WO/GSWeb names
        * GSWeb.framework/GSWCheckBox.m: handle WO/GSWeb names
        * GSWeb.framework/GSWCheckBoxList.m: handle WO/GSWeb names
        * GSWeb.framework/GSWComponentDefinition.m: handle WO/GSWeb names
        * GSWeb.framework/GSWRadioButton.m: handle WO/GSWeb names
        * GSWeb.framework/GSWRadioButtonList.m: handle WO/GSWeb names
        * GSWeb.framework/GSWText.m: handle WO/GSWeb names
        * GSWeb.framework/GSWTextField.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDeployedBundle.m: warnings
        * GSWeb.framework/GSWeb.h: added include GSWeb/GSWSessionTimeOut.h, GSWWOCompatibility.h
        * GSWeb.framework/GSWAdaptor.m: traces
        * GSWeb.framework/GSWDefaultAdaptor.m: handle WO/GSWeb names, added traces
        * GSWeb.framework/GSWDefaultAdaptorThread.m/.h: handle WO/GSWeb names
        * GSWeb.framework/NSNonBlockingFileHandle.m: added traces
        * GSWeb.framework/GSWTemplateParserANTLR.m: handle WO/GSWeb names
        * GSWeb.framework/GSWTemplateParserXML.m: handle WO/GSWeb names
                added tag count to help errors hunt
                remove "Tag gsweb invalid" message
                handle unicode strings in node content traces
                remove html and body tags if they are not present in the template
        * GSWeb.framework/GSWTemplateParseXML.h: added ivar _isHTMLTag, _isBodyTag
        * GSWeb.framework/GSWSessionTimeOutManager.m: dealloc sessionOrderedTimeOuts instead
                of deallocating 2 times sessionTimeOuts
        * GSWExtensions.framework/French.lproj/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
                tag mismatch, Encode french characters
        * GSWExtensions.framework/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
                tag mismatch
        * GSWHTMLBareString.m: handle unicode strings in description
        * GSWExtensions.framework/French.lproj/GSWExceptionPage.gswc/GSWExceptionPage.html:
                Encode french characters, Tag Mismatch
        * GSWExtensions.framework/French.lproj/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.html:
                Encode french characters
        * GSWExtensions.framework/French.lproj/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.html:
                Encode french characters
        * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.html:
                Tag Mismatch
        * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.gswd:
                added convertHTMLEntities for strings
        * GSWeb.framework/GSWRepetition.m: added traces, fix "count" property bug, standardize ivars
        * GSWeb.framework/NSObject+IVarAccess+PerformSel.m: added traces, handle underscored ivars search


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@9332 72102866-910b-0410-8b05-ffd578937521
2001-03-11 17:15:44 +00:00

887 lines
26 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>
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;
LOGClassFnStart();
NSDebugMLLog(@"associations",@"GSWAssociation: keyPath_=%@ object_=%p",keyPath_,(void*)object_);
if (keyPath_ && object_)
{
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];
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
{
NS_DURING
retValue=[retValue getIVarNamed:_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
};
};
};
NSDebugMLLog(@"associations",@"retValue=%@",retValue);
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]));
if (keyPath_)
{
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);
_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
_object=[_object getIVarNamed:_part];
}
else
{
GSWLogAssertGood(_object);
[_object setIVarNamed:_part
withValue:value_];
_object=nil;
};
};
};
}
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();
enumerator = [self keyEnumerator];
while ((_key = [enumerator nextObject]))
{
NSDebugMLLog(@"associations",@"_key=%@",_key);
_var=[self objectForKey:_key];
NSDebugMLLog(@"associations",@"_var=%@",_var);
_varValue=[_var valueInComponent:from_];
NSDebugMLLog(@"associations",@"_varValue=%@",_varValue);
[_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 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