/** GSWComponent.m - GSWeb: Class GSWComponent Copyright (C) 1999-2004 Free Software Foundation, Inc. Written by: Manuel Guesdon Date: Jan 1999 $Revision$ $Date$ $Id$ 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. **/ #include "config.h" RCS_ID("$Id$") #include "GSWeb.h" #include "GSWPrivate.h" #include "WOKeyValueUnarchiver.h" #include #include //==================================================================== @implementation GSWComponent /* Static variables */ static NSMutableDictionary * TheTemplateNameDictionary = nil; static NSLock * TheTemplateNameDictionaryLock = nil; static Class GSWHTMLBareStringClass = Nil; //-------------------------------------------------------------------- + (void) initialize { if (self == [GSWComponent class]) { TheTemplateNameDictionary = [NSMutableDictionary new]; TheTemplateNameDictionaryLock = [[NSLock alloc] init]; GSWHTMLBareStringClass = [GSWHTMLBareString class]; } } //-------------------------------------------------------------------- // deprecated. use initWithContext: -(id)init { // NSLog(@"%s init: deprecated. use initWithContext", class_getName([self class])); return [self initWithContext:[GSWComponentDefinition TheTemporaryContext]]; } //-------------------------------------------------------------------- - (id)initWithContext:(GSWContext *) aContext { Class myClass = Nil; GSWComponentDefinition* aComponentDefinition = nil; if ((self=[super init])) { if (aContext == nil) { [NSException raise:NSInvalidArgumentException format:@"Attempt to init component without a context. In %s", __PRETTY_FUNCTION__]; } [self _setContext:aContext]; myClass = [self class]; if (myClass == [GSWComponent class]) ASSIGN(_name, [aContext _componentName]); else ASSIGN(_name, NSStringFromClass([self class])); ASSIGN(_templateName,NSStringFromClass(myClass)); _isPage = NO; _subComponents = nil; [self setCachingEnabled:[GSWApp isCachingEnabled]]; ASSIGN(_componentDefinition, [aContext _tempComponentDefinition]); aComponentDefinition = [self _componentDefinition]; [aComponentDefinition finishInitializingComponent:self]; _isSynchronized = [self synchronizesVariablesWithBindings]; } return self; } //-------------------------------------------------------------------- -(void)dealloc { DESTROY(_keyAssociations); DESTROY(_childTemplate); DESTROY(_componentDefinition); DESTROY(_defaultAssociations); DESTROY(_name); DESTROY(_subComponents); DESTROY(_template); DESTROY(_templateName); DESTROY(_userAssociations); DESTROY(_userDictionary); DESTROY(_context); //_context=nil; _parent = nil; _session = nil; [super dealloc]; } //-------------------------------------------------------------------- -(id)copyWithZone: (NSZone*)zone { GSWComponent* clone = [[isa allocWithZone: zone] init]; ASSIGNCOPY(clone->_name,_name); ASSIGNCOPY(clone->_subComponents,_subComponents); ASSIGNCOPY(clone->_templateName,_templateName); ASSIGN(clone->_template,_template); ASSIGN(clone->_componentDefinition,_componentDefinition); ASSIGN(clone->_parent,_parent); ASSIGNCOPY(clone->_keyAssociations, _keyAssociations); ASSIGNCOPY(clone->_childTemplate,_childTemplate); ASSIGNCOPY(clone->_context,_context); ASSIGNCOPY(clone->_session,_session); clone->_isPage=_isPage; clone->_isCachingEnabled=_isCachingEnabled; // clone->_isParentToComponentSynchronized=_isParentToComponentSynchronized; // clone->_isComponentToParentSynchronized=_isComponentToParentSynchronized; return clone; } //-------------------------------------------------------------------- //-(void)encodeWithCoder:(NSCoder*)aCoder //{ // //TODOV // [super encodeWithCoder:aCoder]; // [aCoder encodeObject:_name]; // [aCoder encodeObject:_subComponents]; // [aCoder encodeObject:_templateName]; // [aCoder encodeObject:_template]; // [aCoder encodeObject:_componentDefinition]; // [aCoder encodeObject:_parent]; // [aCoder encodeObject:_keyAssociations]; // [aCoder encodeObject:_childTemplate]; // [aCoder encodeObject:_context]; // [aCoder encodeObject:_session]; // [aCoder encodeValueOfObjCType:@encode(BOOL) // at:&_isPage]; // [aCoder encodeValueOfObjCType:@encode(BOOL) // at:&_isCachingEnabled]; //// [aCoder encodeValueOfObjCType:@encode(BOOL) //// at:&_isParentToComponentSynchronized]; //// [aCoder encodeValueOfObjCType:@encode(BOOL) //// at:&_isComponentToParentSynchronized]; //} // ////-------------------------------------------------------------------- //-(id)initWithCoder:(NSCoder*)aCoder //{ // //TODOV // if ((self = [super initWithCoder:aCoder])) // { // [aCoder decodeValueOfObjCType:@encode(id) // at:&_name]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_subComponents]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_templateName]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_template]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_componentDefinition]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_parent]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_keyAssociations]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_childTemplate]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_context]; // [aCoder decodeValueOfObjCType:@encode(id) // at:&_session]; // [aCoder decodeValueOfObjCType:@encode(BOOL) // at:&_isPage]; // [aCoder decodeValueOfObjCType:@encode(BOOL) // at:&_isCachingEnabled]; //// [aCoder decodeValueOfObjCType:@encode(BOOL) //// at:&_isParentToComponentSynchronized]; //// [aCoder decodeValueOfObjCType:@encode(BOOL) //// at:&_isComponentToParentSynchronized]; // } // return self; //} // //-------------------------------------------------------------------- // frameworkName -(NSString*)frameworkName { GSWComponentDefinition* aComponentDefinition=[self _componentDefinition]; NSAssert(aComponentDefinition,@"No componentDefinition"); return [aComponentDefinition frameworkName]; } //-------------------------------------------------------------------- // logString: -(void)logString:(NSString*)aString { [GSWApp logString:aString]; } //-------------------------------------------------------------------- // logWithFormat: -(void)logWithFormat:(NSString*)aFormat,... { va_list ap; va_start(ap,aFormat); [self logWithFormat:aFormat arguments:ap]; va_end(ap); } //-------------------------------------------------------------------- // logWithFormat:arguments: -(void)logWithFormat:(NSString*)aFormat arguments:(va_list)arguments { NSString* string=[NSString stringWithFormat:aFormat arguments:arguments]; [self logString:string]; } //-------------------------------------------------------------------- // name -(NSString*)name { return _name; } //-------------------------------------------------------------------- // path -(NSString*)path { return [[self _componentDefinition] path]; } //-------------------------------------------------------------------- // baseURL -(NSString*)baseURL { return [[self _componentDefinition] baseURL]; } //-------------------------------------------------------------------- -(NSString*)description { return [NSString stringWithFormat:@"<%s %p>", object_getClassName(self), (void*)self]; } // GSWeb Additions { //-------------------------------------------------------------------- -(NSDictionary*)userDictionary { return _userDictionary; } //-------------------------------------------------------------------- -(void)setUserDictionary:(NSDictionary*)aUserDictionary { ASSIGN(_userDictionary,aUserDictionary); } //-------------------------------------------------------------------- -(NSDictionary*)userAssociations { return _userAssociations; } //-------------------------------------------------------------------- -(void)setUserAssociations:(NSDictionary*)userAssociations { ASSIGN(_userAssociations,userAssociations); } //-------------------------------------------------------------------- -(GSWAssociation*)userAssociationForKey:(NSString*)key { return [[self userAssociations]objectForKey:key]; } //-------------------------------------------------------------------- -(NSDictionary*)defaultAssociations { NSLog(@"WARNING: %s is not WebObjects API",__PRETTY_FUNCTION__); return _defaultAssociations; } //-------------------------------------------------------------------- -(void)setDefaultAssociations:(NSDictionary*)defaultAssociations { NSLog(@"WARNING: %s is not WebObjects API",__PRETTY_FUNCTION__); ASSIGN(_defaultAssociations,defaultAssociations); } //-------------------------------------------------------------------- -(GSWAssociation*)defaultAssociationForKey:(NSString*)key { NSLog(@"WARNING: %s is not WebObjects API",__PRETTY_FUNCTION__); return [[self defaultAssociations]objectForKey:key]; } // } //-------------------------------------------------------------------- //setCachingEnabled: -(void)setCachingEnabled:(BOOL)caching { _isCachingEnabled=caching; } //-------------------------------------------------------------------- //isCachingEnabled -(BOOL)isCachingEnabled { return _isCachingEnabled; } //-------------------------------------------------------------------- -(void) _setParent:(GSWComponent*) parent associations:(NSMutableDictionary *) assocdict template:(GSWElement*) template { if (parent != _parent) _parent = parent; if (assocdict != _keyAssociations) ASSIGN(_keyAssociations, assocdict); if (template != _childTemplate) ASSIGN(_childTemplate,template); } //-------------------------------------------------------------------- -(void) _doPushValuesUp { if (_isSynchronized && (_keyAssociations != nil)) { NSEnumerator* enumer = [_keyAssociations keyEnumerator]; NSString* aKey = nil; while ((aKey = [enumer nextObject])) { GSWAssociation* assoc = [_keyAssociations objectForKey: aKey]; if ([assoc isValueSettableInComponent:self]) { [assoc setValue:[self valueForKey: aKey] inComponent:_parent]; } } } } -(void) pushValuesToParent { GSWComponentDefinition * componentdefinition = nil; if (_isSynchronized) { [self _doPushValuesUp]; } componentdefinition = [self _componentDefinition]; if ([componentdefinition isStateless]) { [self reset]; _parent = nil; // no retain? dw _session = nil; DESTROY(_context); [componentdefinition _checkInComponentInstance:self]; } } -(void)synchronizeComponentToParent { NSLog(@"WARNING: %s is deprecated. Use pushValuesToParent instead.", __PRETTY_FUNCTION__); [self pushValuesToParent]; } //-------------------------------------------------------------------- -(void) pullValuesFromParent { if (_isSynchronized && _keyAssociations != nil) { NSEnumerator* enumer = [_keyAssociations keyEnumerator]; NSString* aKey = nil; while ((aKey = [enumer nextObject])) { GSWAssociation* assoc = [_keyAssociations objectForKey: aKey]; id obj = [assoc valueInComponent:_parent]; [self setValue: obj forKey: aKey]; } } } -(void) synchronizeParentToComponent { // NSLog(@"WARNING: %s is deprecated. Use pullValuesFromParent instead.", __PRETTY_FUNCTION__); [self pullValuesFromParent]; } //-------------------------------------------------------------------- -(GSWElement*)_childTemplate { return _childTemplate; } //-------------------------------------------------------------------- -(GSWElement*) template { GSWElement* element = nil; if (_template != element) element = _template; else { element = [self templateWithName:nil]; if ([self isCachingEnabled]) ASSIGN(_template, element); } return element; } //-------------------------------------------------------------------- -(GSWElement*)_template { NSLog(@"WARNING: %s is deprecated. Use template instead.", __PRETTY_FUNCTION__); return [self template]; } //-------------------------------------------------------------------- -(GSWComponentDefinition*)_componentDefinition { GSWComponentDefinition* aComponentDefinition=nil; if (_componentDefinition) aComponentDefinition=_componentDefinition; else { NSArray* languages=[self languages]; aComponentDefinition=[GSWApp _componentDefinitionWithName:_name languages:languages]; if ([self isCachingEnabled]) ASSIGN(_componentDefinition,aComponentDefinition); } return aComponentDefinition; } //-------------------------------------------------------------------- -(NSString*)_templateName { return _templateName; } //-------------------------------------------------------------------- -(NSString*)declarationName { return _templateName; } //-------------------------------------------------------------------- -(BOOL)_isPage { return _isPage; } //-------------------------------------------------------------------- -(void)_setIsPage:(BOOL)isPage { _isPage=isPage; } //-------------------------------------------------------------------- -(void)_setContext:(GSWContext*)aContext { // Verified with WO 4.5. We DO retain! ASSIGN(_context, aContext); } //-------------------------------------------------------------------- // templateWithName: // templateWithName is deprecated but I do not know in which version of WO // MGuesdon;: still exists in 5.0 -(GSWElement*)templateWithName:(NSString*)aName { return [[self _componentDefinition] template]; } //-------------------------------------------------------------------- -(GSWComponent*)subComponentForElementID:(NSString*)elementId { return [_subComponents objectForKey:elementId]; } //-------------------------------------------------------------------- -(void)_setSubcomponent:(GSWComponent*)component forElementID:(NSString*)elementId { if (!_subComponents) _subComponents=[NSMutableDictionary new]; [_subComponents setObject:component forKey:elementId]; } //-------------------------------------------------------------------- //NDFN -(void)makeParentsPerformSelectorIfPossible:(SEL)aSelector { [[self parents] makeObjectsPerformSelectorIfPossible:aSelector]; } //-------------------------------------------------------------------- //NDFN -(void)makeParentsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object { [[self parents] makeObjectsPerformSelectorIfPossible:aSelector withObject:object]; } //-------------------------------------------------------------------- //NDFN -(void)makeParentsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { [[self parents] makeObjectsPerformSelectorIfPossible:aSelector withObject:object1 withObject:object2]; } //-------------------------------------------------------------------- //NDFN -(id)makeAParentPerformSelectorIfPossible:(SEL)aSelector { id retValue=nil; GSWComponent* obj=[self parent]; while(obj) { if ([obj respondsToSelector:aSelector]) { retValue=[obj performSelector:aSelector]; obj=nil; } else obj=[obj parent]; } return retValue; } //-------------------------------------------------------------------- //NDFN -(id)makeAParentPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object { id retValue=nil; GSWComponent* obj=[self parent]; while(obj) { if ([obj respondsToSelector:aSelector]) { retValue=[obj performSelector:aSelector withObject:object]; obj=nil; } else obj=[obj parent]; } return retValue; } //-------------------------------------------------------------------- //NDFN -(id)makeAParentPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { id retValue=nil; GSWComponent* obj=[self parent]; while(obj) { if ([obj respondsToSelector:aSelector]) { retValue=[obj performSelector:aSelector withObject:object1 withObject:object2]; obj=nil; } else obj=[obj parent]; } return retValue; } //-------------------------------------------------------------------- //NDFN -(void)makeSubComponentsPerformSelectorIfPossible:(SEL)aSelector { NSEnumerator* enumerator=nil; GSWComponent* component=nil; enumerator= [_subComponents objectEnumerator]; while ((component=[enumerator nextObject])) { [component performSelectorIfPossible:aSelector]; [component makeSubComponentsPerformSelectorIfPossible:aSelector]; } } //-------------------------------------------------------------------- //NDFN -(void)makeSubComponentsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object { NSEnumerator* enumerator=[_subComponents objectEnumerator]; GSWComponent* component=nil; while ((component=[enumerator nextObject])) { [component performSelectorIfPossible:aSelector withObject:object]; [component makeSubComponentsPerformSelectorIfPossible:aSelector withObject:object]; } } //-------------------------------------------------------------------- //NDFN -(void)makeSubComponentsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { NSEnumerator* enumerator=[_subComponents objectEnumerator]; GSWComponent* component=nil; while ((component=[enumerator nextObject])) { [component performSelectorIfPossible:aSelector withObject:object1 withObject:object2]; [component makeSubComponentsPerformSelectorIfPossible:aSelector withObject:object1 withObject:object2]; } } //PRIVATE -(GSWComponent*) _subcomponentForElementWithID:(NSString*) str { if (_subComponents != nil && str != nil) return [_subComponents objectForKey:str]; else return nil; } //-------------------------------------------------------------------- -(GSWAssociation*)_associationWithName:(NSString*)aName { return [_keyAssociations objectForKey: aName]; } //-------------------------------------------------------------------- -(BOOL)hasBinding:(NSString*)parentBindingName { BOOL hasBinding = NO; GSWAssociation * association = [self _associationWithName: parentBindingName]; hasBinding = (association != nil); if (hasBinding) hasBinding = [association _hasBindingInParent:_parent]; return hasBinding; } //-------------------------------------------------------------------- -(void)setValue:(id)value forBinding:(NSString*)parentBindingName { if (_parent) { GSWAssociation* assoc=[self _associationWithName:parentBindingName]; if(assoc) [assoc setValue:value inComponent:_parent]; } } //-------------------------------------------------------------------- -(id)valueForBinding:(NSString*)parentBindingName { id aValue=nil; if (_parent) { GSWAssociation* assoc=[self _associationWithName:parentBindingName]; if(assoc) aValue=[assoc valueInComponent:_parent]; } return aValue; } //-------------------------------------------------------------------- //NDFN /** Do we need to synchronize parent to component **/ -(BOOL)synchronizesParentToComponentVariablesWithBindings { //OK NSDictionary* userDictionary=nil; id synchronizesParentToComponentVariablesWithBindingsValue=nil; BOOL synchronizesParentToComponentVariablesWithBindings=YES; userDictionary=[self userDictionary]; synchronizesParentToComponentVariablesWithBindingsValue=[userDictionary objectForKey:@"synchronizesParentToComponentVariablesWithBindings"]; //NDFN if (synchronizesParentToComponentVariablesWithBindingsValue) { synchronizesParentToComponentVariablesWithBindings=[synchronizesParentToComponentVariablesWithBindingsValue boolValue]; } else synchronizesParentToComponentVariablesWithBindings=[self synchronizesVariablesWithBindings]; return synchronizesParentToComponentVariablesWithBindings; } //-------------------------------------------------------------------- -(BOOL)synchronizesVariablesWithBindings { return (![self isStateless]); } //-------------------------------------------------------------------- -(BOOL) isStateless { return NO; } //-------------------------------------------------------------------- //NDFN -(NSDictionary*)bindingAssociations { return _keyAssociations; } //-------------------------------------------------------------------- // sleep -(void)sleep { //Does Nothing } //-------------------------------------------------------------------- -(void)sleepInContext:(GSWContext*)aContext { //OK GSWComponentDefinition* aComponentDefinition=nil; NS_DURING { aComponentDefinition=[self _componentDefinition]; [aComponentDefinition sleep]; [self sleep]; [self _setContext:nil]; [_subComponents makeObjectsPerformSelector:@selector(sleepInContext:) withObject:aContext]; } NS_HANDLER { localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,@"In sleepInContext:"); [localException raise]; } NS_ENDHANDLER; } //-------------------------------------------------------------------- // appendToResponse:inContext: -(void)appendToResponse:(GSWResponse*)aResponse inContext:(GSWContext*)aContext { GSWElement * element = nil; [aContext _setResponse: aResponse]; element = [self template]; if (element != nil) { GSWComponent * component = nil; if ([self parent] == nil && [aContext page] != self) { component = [aContext component]; [aContext _setCurrentComponent:self]; } [element appendToResponse: aResponse inContext: aContext]; if (component != nil) { [aContext _setCurrentComponent: component]; } } } //-------------------------------------------------------------------- -(id ) invokeActionForRequest:(GSWRequest*)aRequest inContext:(GSWContext*)aContext { id results = nil; NS_DURING { GSWElement* template = [self template]; if (template != nil) { if ([template class] != GSWHTMLBareStringClass) { results = [template invokeActionForRequest:aRequest inContext:aContext]; } } } NS_HANDLER { localException=ExceptionByAddingUserInfoObjectFrameInfo(localException, @"In %s", __PRETTY_FUNCTION__); [localException raise]; } NS_ENDHANDLER; return results; } //-------------------------------------------------------------------- // takeValuesFromRequest:inContext: -(void)takeValuesFromRequest:(GSWRequest*)aRequest inContext:(GSWContext*)aContext { //OK GSWElement* template=nil; GSWDeclareDebugElementIDsCount(aContext); GSWDeclareDebugElementID(aContext); GSWStartElement(aContext); GSWAssertCorrectElementID(aContext); template=[self template]; [template takeValuesFromRequest:aRequest inContext:aContext]; GSWStopElement(aContext); GSWAssertDebugElementID(aContext); GSWAssertIsElementID(aContext); GSWAssertDebugElementIDsCount(aContext); } //-------------------------------------------------------------------- -(void) _awakeInContext:(GSWContext*)aContext { GSWComponentDefinition* componentdefinition =nil; [self _setContext:aContext]; componentdefinition = [self _componentDefinition]; [componentdefinition setCachingEnabled:[self isCachingEnabled]]; [componentdefinition awake]; if (_subComponents) { [_subComponents makeObjectsPerformSelector:@selector(_awakeInContext:) withObject:aContext]; } _session = nil; [self awake]; } /* Makes sure that the receiver is awake in aContext. Call this method before using a component which was cached in a variable. */ -(void)ensureAwakeInContext:(GSWContext*)aContext { if ([self context] != aContext) [self _awakeInContext:aContext]; } //-------------------------------------------------------------------- -(void) reset { //Does Nothing } -(void)awake { //Does Nothing } -(void)awakeInContext:(GSWContext*)aContext { NSLog(@"WARNING: %s is deprecated. Use _awakeInContext: instead.", __PRETTY_FUNCTION__); [self _awakeInContext:aContext]; } - (id)performParentAction:(NSString *)attribute { GSWContext *context = nil; GSWComponent *component = _parent; id actionresults = nil; if (!_parent) return nil; [context _setCurrentComponent:_parent]; [self pushValuesToParent]; _parent = component; // get the _parent back. context = [self context]; // we do NOT use the iVar to enable fancy subclass magic. NS_DURING { actionresults = [_parent valueForKey: attribute]; } NS_HANDLER { localException=[localException exceptionByAddingUserInfoFrameInfoFormat:@"In %s", __PRETTY_FUNCTION__]; [localException raise]; } NS_ENDHANDLER; [self pullValuesFromParent]; [context _setCurrentComponent:self]; return actionresults; } //-------------------------------------------------------------------- -(GSWComponent*)parent { return _parent; } //-------------------------------------------------------------------- //NDFN -(GSWComponent*)topParent { GSWComponent* parent=[self parent]; GSWComponent* topParent=parent; while (parent) { topParent=parent; parent=[parent parent]; } return topParent; } //-------------------------------------------------------------------- //NDFN -(NSArray*)parents { NSMutableArray* parents=[NSMutableArray array]; GSWComponent* parent=[self parent]; while (parent) { [parents addObject:parent]; parent=[parent parent]; } return [NSArray arrayWithArray:parents]; } //-------------------------------------------------------------------- //NDFN -(NSArray*)parentsClasses { NSMutableArray* parents=[NSMutableArray array]; GSWComponent* parent=[self parent]; while (parent) { [parents addObject:[parent class]]; parent=[parent parent]; } return [NSArray arrayWithArray:parents]; } -(GSWComponent*)pageWithName:(NSString*)aName { GSWComponent* page=nil; GSWContext* aContext=nil; aContext=[self context]; page=[GSWApp pageWithName:aName inContext:aContext]; return page; } //-------------------------------------------------------------------- // session -(GSWSession*)session { GSWSession* session=nil; if (_session) session=_session; else if (_context) session=[_context session]; return session; } //-------------------------------------------------------------------- -(BOOL)hasSession { return (_session!=nil); } //-------------------------------------------------------------------- // application -(GSWApplication*)application { return [GSWApplication application]; } //-------------------------------------------------------------------- // context -(GSWContext*)context { GSWContext * ctx = nil; if (_context == nil && _session != nil) { if ((ctx = [_session context])) { [self _awakeInContext: ctx]; [_context _takeAwakeComponent:self]; } } return _context; } //-------------------------------------------------------------------- //NDFN -(NSArray*)languages { return [[self context] languages]; } //-------------------------------------------------------------------- //Called when an Enterprise Object or formatter failed validation during an //assignment. //The default implementation ignores the error. Subclassers can override to // record the error and possibly return a different page for the current action. - (void) validationFailedWithException:(NSException *)exception value:(id)value keyPath:(NSString *)keyPath { // FIXME: check if that code is in WO4.x /* if ([self hasSession]) { [[self session] validationFailedWithException:exception value:value keyPath:keyPath component:self]; } else { [GSWApp validationFailedWithException:exception value:value keyPath:keyPath component:self session:null]; } */ } //-------------------------------------------------------------------- -(void)_debugWithString:(NSString*)string { [self notImplemented: _cmd]; //TODOFN /* Seems there's a problem with patches... Why this code is here ? if (![self context]) { NSDebugMLLog(@"GSWComponent",@"component sleeps, we awake it = %@",self); [self awakeInContext:aContext]; } else { if ([self context] != aContext) { NSDebugMLLog(@"GSWComponent",@"component is already awaken, but has not the current context, we awake it twice with current context = %@",self); [self awakeInContext:aContext]; } } */ } //-------------------------------------------------------------------- -(void)debugWithFormat:(NSString*)aFormat,... { [self notImplemented: _cmd]; //TODOFN } //-------------------------------------------------------------------- +(void)logWithFormat:(NSString*)aFormat,... { va_list ap; va_start(ap,aFormat); [[GSWApplication application] logWithFormat:aFormat arguments:ap]; va_end(ap); } //-------------------------------------------------------------------- -(void)_appendPageToResponse:(GSWResponse*)response inContext:(GSWContext*)aContext { NSAssert(aContext,@"No context"); NS_DURING { GSWSession* session=nil; NSString* httpVersion=@"HTTP/1.0"; GSWElement* pageElement=nil; BOOL pageChanged=NO; GSWRequest* request=[aContext request]; GSWContext_deleteAllElementIDComponents(aContext); if (request != nil) httpVersion = [request httpVersion]; [response setHTTPVersion:httpVersion]; [response setHeader:@"text/html" forKey:GSWHTTPHeader_ContentType]; [aContext _setResponse:response]; pageElement=[aContext _pageElement]; pageChanged=(self!=(GSWComponent*)pageElement); [aContext _setPageChanged:pageChanged]; if (pageChanged) [aContext _setPageElement:self]; [aContext _setCurrentComponent:self]; [self appendToResponse:response inContext:aContext]; session=[aContext _session]; if (session) { [session appendCookieToResponse:response]; [session _saveCurrentPage]; } [aContext _incrementContextID]; GSWContext_deleteAllElementIDComponents(aContext); [aContext _setPageChanged:YES]; } NS_HANDLER { NSLog(@"localException is %@", localException); localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, @"in GSWComponent -_generateResponseInContext:"); [localException raise]; } NS_ENDHANDLER; } //-------------------------------------------------------------------- -(GSWResponse*)_generateResponseInContext:(GSWContext*)aContext { GSWResponse* response=nil; NSAssert(aContext,@"No context"); response=[GSWApp createResponseInContext:aContext]; [self _appendPageToResponse:response inContext:aContext]; return response; } //-------------------------------------------------------------------- // actually this is wrong. it should call the validateValue:forKey: of the default implementation // as such it should call the validateXXX stuff like EOs do. dave@turbocat.de -(NSException*)validateValue:(id*)valuePtr forKey:(NSString*)key { NSException* exception=nil; /* // Should all default implementation (i.e. the one which call validateXX: exception=[super validateValue:valuePtr forKey:key]; */ return exception; } /** * This method is called to validate and potentially coerce * VALUE for the receivers key path. This method also assigns * the value if it is different from the current value. * This method will raise an EOValidationException * if validateValue:forKeyPath:error: returns an error. * This method returns new value. **/ - (id)validateTakeValue:(id)value forKeyPath:(NSString *)path { if (!path) { [NSException raise:NSInvalidArgumentException format:@"keyPath must not be nil"]; } else { NSError * outError = nil; NSString * validatePath = path; id targetObject = self; NSRange dotRange = [path rangeOfString:@"." options:NSBackwardsSearch]; if (dotRange.location != NSNotFound) { NSString * newPath = [path substringToIndex:dotRange.location]; targetObject = [self valueForKeyPath:newPath]; if (!targetObject) { // If there is no object to set a value, we cannot do any validation. // There is nothing to set on a non-existing object, so just go. return nil; } // 1 is the length of the "." validatePath = [path substringFromIndex: dotRange.location+1]; } if ([targetObject validateValue:&value forKeyPath:validatePath error:&outError]) { id oldValue=[self valueForKeyPath:path]; if (SBIsValueEqual(oldValue,value)==NO) { //Set it if it differ from previous value [self setValue:value forKeyPath:path]; } return value; } else { NSString * errorStr = @"unknown reason"; NSException * exception=nil; NSDictionary * uInfo = nil; uInfo = [NSDictionary dictionaryWithObjectsAndKeys: (value ? value : (id)@"nil"), @"EOValidatedObjectUserInfoKey", path, @"EOValidatedPropertyUserInfoKey", nil]; if (outError && [outError userInfo]) { errorStr = [[outError userInfo] valueForKey:NSLocalizedDescriptionKey]; } exception=[NSException exceptionWithName:@"EOValidationException" reason:errorStr userInfo:uInfo]; [exception raise]; } } return value; } //-------------------------------------------------------------------- // urlForResourceNamed:ofType: -(NSString*)urlForResourceNamed:(NSString*)aName ofType:(NSString*)type { NSString* url = nil; GSOnceMLog(@"%s is deprecated in WO 4.0. Use GSWResourceManager’s implementation of " @"urlForResourceNamed:inFramework:languages:request: " @"instead.", __PRETTY_FUNCTION__); url=[[GSWApp resourceManager] urlForResourceNamed:aName inFramework:nil languages:[self languages] request:nil]; return url; } //-------------------------------------------------------------------- -(NSString*)pathForResourceNamed:(NSString*)aName ofType:(NSString*)type { NSString* path=nil; GSOnceMLog(@"%s is deprecated in WO 4.0. Use GSWResourceManager’s implementation of " @"pathForResourceNamed:inFramework:languages: " @"instead.", __PRETTY_FUNCTION__); path=[[GSWApp resourceManager] pathForResourceNamed:aName inFramework:nil languages:[self languages]]; return path; } //-------------------------------------------------------------------- // templateWithHTMLString:declarationString:languages //-------------------------------------------------------------------- +(GSWElement*)templateWithHTMLString:(NSString*)htmlString declarationString:(NSString*)pageDefString languages:(NSArray*)languages { return [GSWTemplateParser templateWithHTMLString:htmlString declarationString:pageDefString languages:languages]; } //-------------------------------------------------------------------- // templateWithHTMLString:declarationString: +(GSWElement*)templateWithHTMLString:(NSString*)htmlString declarationString:(NSString*)pageDefString { GSOnceMLog(@"%s is deprecated in WO 4.0. Use " @"templateWithHTMLString:declarationString:languages:" @"instead.", __PRETTY_FUNCTION__); return [self templateWithHTMLString:htmlString declarationString:pageDefString languages:nil]; } //-------------------------------------------------------------------- -(GSWResponse*)generateResponse { return [self _generateResponseInContext: [self context]]; } //-------------------------------------------------------------------- // descriptionForResponse:inContext: -(NSString*)descriptionForResponse:(GSWResponse*)aResponse inContext:(GSWContext*)aContext { return _name; } //-------------------------------------------------------------------- - (WOMarkupType) markupType { return WOHTML401Markup; } //-------------------------------------------------------------------- +(void)_registerObserver:(id)observer { [self notImplemented: _cmd]; //TODOFN } //-------------------------------------------------------------------- -(id) unarchiver: (WOKeyValueUnarchiver*)archiver objectForReference: (id)keyPath { if ([keyPath isKindOfClass:[NSString class]]) { return [self valueForKeyPath:keyPath]; } return nil; } @end