/*!
@header ECXMLControlDefaultRule
@abstract Module of Encore
@availability OS X, GNUstep
@copyright 2004, 2005, 2006 Oliver Langer
Author: Oliver Langer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------
Modification history
27.11.05 ola initial version
22.08.06 ola license changed
-------------------------------------------------------------------------
*/
#include
#include
@implementation ECXMLControlSetAttributeRule
- init {
self = [super init];
self->setterLookupUtil = [[ECXMLControlSetterLookupUtil alloc] init];
return self;
}
- (void) dealloc {
if( nil != self->setterLookupUtil ) {
[self->setterLookupUtil release];
}
[super dealloc];
}
- (BOOL) mayActOn: (ECXMLControlContext *) aContext {
return [[[aContext event] eventId]
isEqual: [ECXMLControlEvent eventId_addAttribute]];
}
- (BOOL) actOn: (ECXMLControlContext *) aContext {
id userObject;
BOOL ignoreSubsequentRules = NO;
NSAssert( [[[aContext event] eventId]
isEqual: [ECXMLControlEvent eventId_addAttribute]],
@"ECXMLControlSetAttributeRule::actOn: Expected an addAttribute event!" );
// fetch user object at top position
userObject = [[aContext state] userObjectAtTopPosition];
if( nil == userObject ) {
return NO;
}
EC_AUTORELEASEPOOL_BEGIN
SEL methodToCall = [self->setterLookupUtil
lookupMethodForAttributeName: [[aContext event] attributeName]
ofObject: userObject];
if( NULL != methodToCall ) {
[userObject performSelector: methodToCall
withObject: [[aContext event] attributeValue]];
ignoreSubsequentRules = YES;
}
EC_AUTORELEASEPOOL_END
return ignoreSubsequentRules;
}
@end
// ------------------------------------- ECXMLControlLinkObjectRule
@implementation ECXMLControlLinkObjectRule
- init {
self = [super init];
self->setterLookupUtil = [[ECXMLControlSetterLookupUtil alloc] init];
return self;
}
- (void) dealloc {
if( nil != self->setterLookupUtil ) {
[self->setterLookupUtil release];
}
[super dealloc];
}
- (BOOL) actOn: (ECXMLControlContext *) aContext {
BOOL elementRemovedFromStack = NO;
NSAssert( [[[aContext event] eventId] isEqual:
[ECXMLControlEvent eventId_elementEnded]],
@"ECXMLControlLinkObjectRule::actOn: Expected an END ELEMENT event!" );
EC_AUTORELEASEPOOL_BEGIN
if( [[aContext state] countStackObjects] > 1 ) {
/*
* For the current top user object there exists a (potential) parent
* object -> so remove it from the stack and add (link) it to the parent
* object
*/
id oldTopUserObject = [[[aContext state] popUserObject] autorelease];
SEL methodToCall;
elementRemovedFromStack = YES;
/**
* Look up for a related setter method of the current (new) top object.
* Call it, if existent
*/
methodToCall = [self->setterLookupUtil
lookupMethodForAttributeName: [[aContext event] elementName]
ofObject: [[aContext state] userObjectAtTopPosition]];
if( NULL != methodToCall ) {
[[[aContext state] userObjectAtTopPosition]
performSelector: methodToCall
withObject: oldTopUserObject];
}
}
EC_AUTORELEASEPOOL_END
return elementRemovedFromStack;
}
- (BOOL) mayActOn: (ECXMLControlContext *) aContext {
return [[[aContext event] eventId] isEqual:
[ECXMLControlEvent eventId_elementEnded]];
}
@end
// ------------------------------------- ECXMLControlSetterLookupUtil
@implementation ECXMLControlSetterLookupUtil
- init {
self = [super init];
self->namesForSetterMethods = [[NSMutableArray alloc] init];
/*
* The following format strings must contain "%@%@", where the
* first substitution string will be replaced by the first letter of
* the attribute name, which may be in lower or in upper case. The remaining
* substition string will be replaced by the remaining characters of the
* attribute name
*/
[self addMethodNameSchema: @"set%@%@:"];
[self addMethodNameSchema: @"add%@%@:"];
return self;
}
- (void) dealloc {
if( nil != self->namesForSetterMethods ) {
[self->namesForSetterMethods release];
}
[super dealloc];
}
- addMethodNameSchema: (NSString *) aMethodNameSchema {
[self->namesForSetterMethods addObject: aMethodNameSchema];
return self;
}
- (SEL) lookupMethodForAttributeName: (NSString *) anAttributeName
ofObject: (id) aTargetObject {
SEL toReturn = NULL;
EC_AUTORELEASEPOOL_BEGIN
SEL methodToCall;
int i;
NSString *firstCharacter = [anAttributeName substringToIndex: 1];
NSString *remainingChars = [anAttributeName substringFromIndex: 1];
for( i = 0; i < [self->namesForSetterMethods count]; i++ ) {
NSString *methodName;
// try with the first character as uppercase character
methodName = [[[NSString alloc]
initWithFormat: [self->namesForSetterMethods objectAtIndex: i],
[firstCharacter uppercaseString],
remainingChars] autorelease];
methodToCall = NSSelectorFromString( methodName );
if( NULL != methodToCall ) {
if( [aTargetObject respondsToSelector: methodToCall] ) {
// method found
toReturn = methodToCall;
break;
}
}
// try with the first character as lowercase character
methodName = [[[NSString alloc]
initWithFormat: [self->namesForSetterMethods objectAtIndex: i],
[firstCharacter lowercaseString],
remainingChars] autorelease];
methodToCall = NSSelectorFromString( methodName );
if( NULL != methodToCall ) {
if( [aTargetObject respondsToSelector: methodToCall] ) {
// method found
toReturn = methodToCall;
break;
}
}
}
EC_AUTORELEASEPOOL_END
return toReturn;
}
@end