/*!
@header ECXMLControl
@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
#include
#include
#include
#include
#include
#include
#include
@implementation ECXMLControl
- internalInit {
self->state = [[ECXMLControlState alloc] init];
self->ruleSelector = [[ECXMLControlRuleSelector alloc] init];
self->defaultRulesAdded = NO;
self->defaultRulesEnabled = YES;
self->errorHandler = nil;
self->errorHandlerMethod = NULL;
return self;
}
- initWithContentsOfURL: (NSURL *) anURL {
self = [super init];
self->parser = [[NSXMLParser alloc] initWithContentsOfURL: anURL];
[self internalInit];
return self;
}
- initWithData: (NSData *) data {
self = [super init];
self->parser = [[NSXMLParser alloc] initWithData: data];
[self internalInit];
return self;
}
- (void) dealloc {
if( nil != self->parser ) {
[self->parser release];
}
if( nil != self->ruleSelector ) {
[self->ruleSelector release];
}
[self->errorHandler release];
[super dealloc];
}
- (NSArray *) userObjects {
NSArray *toReturn = nil;
if( nil == self->state ) {
toReturn = [[[NSMutableArray alloc] init] autorelease];
} else {
if( nil == [self->state allUserObjects] ) {
toReturn = [[[NSMutableArray alloc] init] autorelease];
} else {
toReturn = [self->state allUserObjects];
}
}
return toReturn;
}
- addDefaultRules {
/* add rule which is responsible for allocating objects */
[self->ruleSelector addRule:
[[[ECXMLControlDefaultAllocatorRule alloc] init] autorelease]
forEvent: [ECXMLControlEvent eventId_elementStarted]];
/* add a rule which allows the usage of id and id-ref like mechanism by
* which objects can be references see ECControlReferenceRule for more details
*/
[self->ruleSelector addRule:
[[[ECXMLControlReferenceRule alloc] init] autorelease]
forEvent: [ECXMLControlEvent eventId_addAttribute]];
// add rule which is responsible to lookup and call appropriate setting
// methods for given attributes
[self->ruleSelector addRule:
[[[ECXMLControlSetAttributeRule alloc] init] autorelease]
forEvent: [ECXMLControlEvent eventId_addAttribute]];
// add a rule which links nested objects together
[self->ruleSelector addRule:
[[[ECXMLControlLinkObjectRule alloc] init] autorelease]
forEvent: [ECXMLControlEvent eventId_elementEnded]];
self->defaultRulesAdded = YES;
return self;
}
- enableDefaultRules: (BOOL) enable {
self->defaultRulesEnabled = enable;
return self;
}
- parseXML {
NSAssert( nil != self->parser, @"ECXMLControl::parseXML: Controller"\
" not correctly installed!" );
EC_AUTORELEASEPOOL_BEGIN
[self->parser setDelegate: self];
[self->parser setShouldResolveExternalEntities: NO];
[self->parser setShouldProcessNamespaces: NO];
if( (!self->defaultRulesAdded) && (self->defaultRulesEnabled)) {
[self addDefaultRules];
self->defaultRulesAdded = YES;
}
[self->parser parse];
EC_AUTORELEASEPOOL_END
return self;
}
- (void) parser: (NSXMLParser*)aParser
didEndElement: (NSString*)anElementName
namespaceURI: (NSString*)aNamespaceURI
qualifiedName: (NSString*)aQualifierName {
EC_AUTORELEASEPOOL_BEGIN
ECXMLControlEvent *event = [[[ECXMLControlEvent alloc]
initElementEndedEventWithName: anElementName] autorelease];
ECXMLControlContext *context;
context = [[[ECXMLControlContext alloc]
initWithState: self->state
causedEvent: event] autorelease];
[self->ruleSelector performRulesForContext: context];
EC_AUTORELEASEPOOL_END
return;
}
- (void) parser: (NSXMLParser*) aParser
didStartElement: (NSString*) anElementName
namespaceURI: (NSString*) aNamespaceURI
qualifiedName: (NSString*) aQualifierName
attributes: (NSDictionary*) anAttributeDict {
EC_AUTORELEASEPOOL_BEGIN
NSEnumerator *allAttributes;
id attributeName;
ECXMLControlEvent *event = [[[ECXMLControlEvent alloc]
initElementStartedEventWithName: anElementName
withAttributes: anAttributeDict ] autorelease];
ECXMLControlContext *context;
context = [[[ECXMLControlContext alloc]
initWithState: self->state
causedEvent: event] autorelease];
[self->ruleSelector performRulesForContext: context];
// now fire events where each event specifies an attribute
allAttributes = [anAttributeDict keyEnumerator];
while( (attributeName = [allAttributes nextObject]) ) {
event = [[[ECXMLControlEvent alloc]
initAddAttributeEventWithName: anElementName
withAttributeName: attributeName
withAttributeValue: [anAttributeDict objectForKey: attributeName]]
autorelease];
context = [[[ECXMLControlContext alloc]
initWithState: self->state
causedEvent: event] autorelease];
[self->ruleSelector performRulesForContext: context];
}
EC_AUTORELEASEPOOL_END
}
- (void)parser:(NSXMLParser *)aParser parseErrorOccurred:(NSError *)parseError {
if( nil != self->errorHandler ) {
if( NULL != self->errorHandlerMethod ) {
[self->errorHandler
performSelector: self->errorHandlerMethod
withObject: parseError];
}
}
}
- (id) rootUserObject {
NSArray *userObjects = [self userObjects];
id toReturn = nil;
if( 0 < [userObjects count] ) {
toReturn = [userObjects objectAtIndex: 0];
}
return toReturn;
}
- (ECXMLControlRuleSelector *) ruleSelector {
return self->ruleSelector;
}
- delegateErrorsTo: (id) anErrorHandler usingMethod: (SEL) aMethod {
id tmp = self->errorHandler;
self->errorHandler = [anErrorHandler retain];
[tmp release];
self->errorHandlerMethod = aMethod;
return self;
}
@end