/*
- Copyright (C) 2000-2004 SKYRIX Software AG
+ Copyright (C) 2000-2005 SKYRIX Software AG
- This file is part of OpenGroupware.org.
+ This file is part of SOPE.
- OGo is free software; you can redistribute it and/or modify it under
+ SOPE 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, or (at your option) any
later version.
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+ SOPE 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 OGo; see the file COPYING. If not, write to the
+ License along with SOPE; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include <NGObjWeb/WOElement.h>
#include <NGObjWeb/WOAssociation.h>
#include <NGObjWeb/WOComponentScript.h>
+#include <NGObjWeb/WODynamicElement.h>
#include "WOComponentFault.h"
#include "common.h"
@interface WOElement(UsedPrivates)
- (id)initWithValue:(id)_value escapeHTML:(BOOL)_flag;
++ (id)allocForCount:(int)_count zone:(NSZone *)_zone;
+- (id)initWithContentElements:(NSArray *)_elements;
@end
@interface WOAssociation(misc)
/* operations */
-- (WOComponent *)instantiateWithResourceManager:(WOResourceManager *)_rm
+- (id)instantiateWithResourceManager:(WOResourceManager *)_rm
languages:(NSArray *)_languages
{
static Class FaultClass = Nil;
@implementation WOxElemBuilder
-static Class StrClass = Nil;
-static Class AStrClass = Nil;
-static NSDictionary *defaultAssocMap = nil;
-static Class ValAssoc = Nil;
-static BOOL logAssocMap = NO;
-static BOOL logAssocCreation = NO;
-static BOOL debugOn = NO;
+static Class StrClass = Nil;
+static Class AStrClass = Nil;
+static NSDictionary *defaultAssocMap = nil;
+static Class ValAssoc = Nil;
+static BOOL logAssocMap = NO;
+static BOOL logAssocCreation = NO;
+static BOOL debugOn = NO;
+static NGLogger *logger = nil;
+static Class CompoundElemClass = Nil;
+static NSNumber *yesNum = nil;
+static WOAssociation *yesAssoc = nil;
+ (int)version {
return 1;
}
+ (void)initialize {
- NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
+ NSUserDefaults *ud;
+ NGLoggerManager *lm;
static BOOL didInit = NO;
+
if (didInit) return;
didInit = YES;
-
+
+ ud = [NSUserDefaults standardUserDefaults];
+ lm = [NGLoggerManager defaultLoggerManager];
+
+ logger = [lm loggerForClass:self];
+ [logger setLogLevel:[WOApplication isDebuggingEnabled] ? NGLogLevelDebug
+ : NGLogLevelInfo];
+
StrClass = NSClassFromString(@"_WOSimpleStaticString");
if (StrClass == Nil)
- NSLog(@"ERROR: missing class _WOSimpleStaticString !");
+ [logger errorWithFormat:@"missing class _WOSimpleStaticString !"];
AStrClass = NSClassFromString(@"_WOSimpleStaticASCIIString");
if (AStrClass == Nil)
- NSLog(@"ERROR: missing class _WOSimpleStaticASCIIString !");
+ [logger errorWithFormat:@"missing class _WOSimpleStaticASCIIString !"];
logAssocMap = [ud boolForKey:@"WOxElemBuilder_LogAssociationMapping"];
logAssocCreation =
[ud boolForKey:@"WOxElemBuilder_LogAssociationCreation"];
- if (logAssocMap) NSLog(@"Note: association mapping is logged!");
- if (logAssocCreation) NSLog(@"Note: association creation is logged!");
-
+ if (logAssocMap)
+ [logger logWithFormat:@"association mapping is logged!"];
+ if (logAssocCreation)
+ [logger logWithFormat:@"association creation is logged!"];
+
+ // TODO: improve extensibility of this (remember WOWrapperTemplateBuilder)
defaultAssocMap = [[ud dictionaryForKey:@"WOxAssociationClassMapping"] copy];
if (defaultAssocMap == nil)
- NSLog(@"WARNING: WOxAssociationClassMapping default is not set!");
+ [logger warnWithFormat:
+ @"WOxAssociationClassMapping default is not set!"];
if (ValAssoc == Nil)
ValAssoc = NSClassFromString(@"WOValueAssociation");
+
+ CompoundElemClass = NSClassFromString(@"WOCompoundElement");
+
+ if (yesNum == nil)
+ yesNum = [[NSNumber numberWithBool:YES] retain];
+ if (yesAssoc == nil)
+ yesAssoc = [[WOAssociation associationWithValue:yesNum] retain];
}
+ (WOxElemBuilder *)createBuilderQueue:(NSArray *)_classNames {
- unsigned i, count;
+ unsigned i, count;
WOxElemBuilder *first, *current = nil;
NSMutableArray *missingBuilders = nil;
c = [self associationClassForNamespaceURI:[_attribute namespaceURI]];
if (c == Nil) {
- [self logWithFormat:
- @"WARNING, found no association class for "
- @"attribute %@ (namespace=%@)",
+ [self warnWithFormat:
+ @"found no association class for attribute %@ (namespace=%@)",
_attribute, [_attribute namespaceURI]];
return nil;
}
if (logAssocMap) {
[self logWithFormat:@"use class %@ for namespaceURI %@ (attribute %@)",
- c, [_attribute namespaceURI], [_attribute name]];
+ c, [_attribute namespaceURI], [_attribute name]];
}
assoc = [[c alloc] initWithString:value];
if (logAssocCreation) {
[self logWithFormat:@"created assoc %@ for attribute %@",
- assoc, [_attribute name]];
+ assoc, [_attribute name]];
}
return [assoc autorelease];
self->nsToAssoc = [[NSMutableDictionary alloc] initWithCapacity:8];
e = [defaultAssocMap keyEnumerator];
- while ((ns = [e nextObject])) {
+ while ((ns = [e nextObject]) != nil) {
NSString *className;
Class clazz;
clazz = NSClassFromString(className);
if (clazz == Nil) {
- [self logWithFormat:@"WARNING: did not find association class: '%@'",
+ [self warnWithFormat:@"did not find association class: '%@'",
className];
continue;
}
[self _ensureDefaultAssocMappings];
- if ((c = [self->nsToAssoc objectForKey:_ns]) == nil)
+ if ((c = [self->nsToAssoc objectForKey:_ns]) == Nil)
/* if we have no class mapped for a namespace, we treat it as a value */
c = ValAssoc;
/* logging */
++ (id)logger {
+ return logger;
+}
+- (id)logger {
+ return logger;
+}
+
- (void)logWithFormat:(NSString *)_format, ... {
NSString *value = nil;
va_list ap;
- (void)reset {
[self->subcomponentInfos removeAllObjects];
- ASSIGN(self->script, (id)nil);
+ [self->script release]; self->script = nil;
}
-@end /* WOxElemBuilder */
+/* support methods for subclasses */
-@implementation WOxTagClassElemBuilder
+- (id<DOMElement>)lookupUniqueTag:(NSString *)_name
+ inElement:(id<DOMElement>)_elem
+{
+ id<DOMNodeList> list;
+
+ if ((list = [_elem getElementsByTagName:_name]) == nil)
+ return nil;
+ if ([list length] == 0)
+ return nil;
+ if ([list length] > 1) {
+ [self warnWithFormat:
+ @"more than once occurence of tag %@ in element: %@",
+ _name, _elem];
+ }
+ return [list objectAtIndex:0];
+}
-- (Class)classForElement:(id<DOMElement>)_element {
- return Nil;
+- (WOElement *)elementForRawString:(NSString *)_rawstr {
+ /* Note: returns a retained element! */
+ WOAssociation *a;
+
+ if (_rawstr == nil) return nil;
+ a = [WOAssociation associationWithValue:_rawstr];
+ return [[StrClass alloc] initWithValue:a escapeHTML:NO];
}
-- (WOElement *)buildElement:(id<DOMElement>)_element templateBuilder:(id)_b {
- Class clazz;
+- (WOElement *)elementForElementsAndStrings:(NSArray *)_elements {
+ /* Note: returns a retained element! */
+ NSMutableArray *ma;
+ WOElement *element;
+ unsigned i, count;
- if ((clazz = [self classForElement:_element]) == Nil) {
- if (self->nextBuilder)
- return [self->nextBuilder buildElement:_element templateBuilder:_b];
- else {
- [self logWithFormat:
- @"did not find dynamic element class for DOM element %@",
- _element];
- return nil;
+ if ((count = [_elements count]) == 0)
+ return nil;
+
+ ma = [[NSMutableArray alloc] initWithCapacity:count];
+ for (i = 0; i < count; i++) {
+ id elem;
+
+ elem = [_elements objectAtIndex:i];
+ if ([elem isKindOfClass:[WOElement class]]) {
+ [ma addObject:elem];
+ continue;
}
+
+ if ((elem = [self elementForRawString:[elem stringValue]]))
+ [ma addObject:elem];
+ }
+ if ((count = [ma count]) == 0)
+ element = nil;
+ else if (count == 1) {
+ element = [[ma objectAtIndex:0] retain];
+ }
+ else {
+ element = [[CompoundElemClass allocForCount:count zone:NULL]
+ initWithContentElements:ma];
+ }
+ [ma release];
+ return element;
+}
+
+- (WOElement *)wrapElement:(WOElement *)_element
+ inCondition:(WOAssociation *)_condition
+ negate:(BOOL)_flag
+{
+ // NOTE: *releases* _element parameter!
+ // returns retained conditional
+ static Class WOConditionalClass = Nil;
+ static NSString *key = @"condition";
+ NSMutableDictionary *assocs;
+ WOElement *element;
+ NSArray *children;
+
+ if (WOConditionalClass == Nil)
+ WOConditionalClass = NSClassFromString(@"WOConditional");
+
+ if (_element == nil)
+ return nil;
+ if (_condition == nil)
+ return _element;
+
+ if (_flag) {
+ assocs = [[NSMutableDictionary alloc]
+ initWithObjectsAndKeys:_condition, key,
+ yesAssoc, @"negate", nil];
}
- return [[clazz alloc] initWithElement:_element templateBuilder:_b];
+ else {
+ assocs = [[NSMutableDictionary alloc] initWithObjects:&_condition
+ forKeys:&key count:1];
+ }
+ children = [[NSArray alloc] initWithObjects:&_element count:1];
+ element = [[WOConditionalClass alloc] initWithName:nil
+ associations:assocs
+ contentElements:children];
+ [children release];
+ [_element release];
+ [assocs release];
+ return element;
+}
+
+- (WOElement *)wrapElements:(NSArray *)_sub inElementOfClass:(Class)_class {
+ WOElement *element;
+
+ if (_sub == nil)
+ return nil;
+
+ element = [[_class alloc] initWithName:nil
+ associations:nil
+ contentElements:_sub];
+ return element;
}
-@end /* SxTagClassElemBuilder */
+- (WOElement *)wrapChildrenOfElement:(id<DOMElement>)_tag
+ inElementOfClass:(Class)_class
+ templateBuilder:(id)_b
+{
+ NSArray *children;
+
+ children = [_tag hasChildNodes]
+ ? [_b buildNodes:[_tag childNodes] templateBuilder:_b]
+ : nil;
+
+ return [self wrapElements:children inElementOfClass:_class];
+}
+
+@end /* WOxElemBuilder */