)_element templateBuilder:(id)_b {
/*
...
*/
NSMutableArray *ma;
NSArray *children;
WOElement *element;
children = [_element hasChildNodes]
? [_b buildNodes:[_element childNodes] templateBuilder:_b]
: (NSArray *)nil;
ma = [[NSMutableArray alloc] initWithCapacity:[children count] + 3];
[ma addObject:@""]; // TODO: add CSS class
if ((element = [self wrapElements:children inElement:[self fontClass]])) {
[ma addObject:element];
[element release]; element = nil;
}
[ma addObject:@"
"];
element = [self elementForElementsAndStrings:ma];
[ma release];
return element;
}
- (WOElement *)buildPageWarn:(id)_element templateBuilder:(id)_b {
/*
okAction - always keypath
warningPhrase - regular assoc
...
Builds:
Warning: LSWWarningPanel {
onOk = warningOkAction;
phrase = warningPhrase;
}
*/
NSMutableDictionary *assocs;
id attr;
NSString *cid, *s;
if (debugOn) [self debugWithFormat:@" build OGo page-warn: %@", _element];
/* unique component ID */
cid = [_b uniqueIDForNode:_element];
if (debugOn) [self debugWithFormat:@" CID: %@", cid];
/* setup associations */
assocs = [[NSMutableDictionary alloc] initWithCapacity:4];
if ((s = [_element attribute:@"okAction" namespaceURI:@"*"]) != nil) {
[assocs setObject:[WOAssociation associationWithKeyPath:s]
forKey:@"onOk"];
}
if ((attr = [[_element attributes] namedItem:@"phrase" namespaceURI:@"*"]))
[assocs setObject:[_b associationForAttribute:attr] forKey:@"phrase"];
/* create component */
[_b registerSubComponentWithId:cid
componentName:[self warningComponentName] bindings:assocs];
[assocs release]; assocs = nil;
return [[ChildRefClass alloc]
initWithName:cid associations:nil contentElements:nil];
}
- (WOElement *)buildPage:(id)_element templateBuilder:(id)_b {
/*
This builds the common content page wrapper:
<#Frame><#Window>...#Window>#Frame>
where "Frame" is LSWSkyrixFrame (component) and "Window" is
OGoWindowFrame (element). Window has the parameters "title" and "onClose".
It is extended to build some specific subelements like:
xyz
TODO: add support for SkyCalendarScript (should be first element in frame)
Calendar: SkyCalendarScript {}
TODO: add support for generating "focus" (JavaScript) scripts, like:
if (document.personEditor) {
if (document.personEditor.elements[0])
document.personEditor.elements[0].focus();
}
=> this is now supported by OGoWindowFrame!
*/
NSMutableDictionary *assocs;
NSArray *children, *frameChildren;
NSString *cid;
WOElement *window;
id tmp;
if (debugOn) [self debugWithFormat:@" build OGo page: %@", _element];
/* unique component ID */
cid = [_b uniqueIDForNode:_element];
if (debugOn) [self debugWithFormat:@" CID: %@", cid];
/* construct child elements (rework for OGo:body?) */
if ((tmp = [self lookupUniqueTag:@"body" inElement:_element]) != nil) {
/* mode a: explicit hierarchy with 'head' and 'body' subelements */
WOElement *head, *body, *warn;
body = [self buildPageBody:tmp templateBuilder:_b];
head = ((tmp = [self lookupUniqueTag:@"head" inElement:_element]) != nil)
? [self buildPageHead:tmp templateBuilder:_b]
: (WOElement *)nil;
warn = ((tmp = [self lookupUniqueTag:@"warn" inElement:_element]) != nil)
? [self buildPageWarn:tmp templateBuilder:_b] : (WOElement *)nil;
if (warn != nil) {
/* wrap body / wrap warn using 'isInWarningMode' binding */
static WOAssociation *warnAssoc = nil; // THREAD
if (warnAssoc == nil) {
warnAssoc =
[[WOAssociation associationWithKeyPath:@"isInWarningMode"] copy];
}
if (head != nil)
head = [self wrapElement:head inCondition:warnAssoc negate:YES];
body = [self wrapElement:body inCondition:warnAssoc negate:YES];
warn = [self wrapElement:warn inCondition:warnAssoc negate:NO];
}
children = (head != nil)
? [NSArray arrayWithObjects:head, body, warn, nil]
: [NSArray arrayWithObjects:body, warn, nil];
[head release]; head = nil;
[body release]; body = nil;
[warn release]; warn = nil;
}
else {
/* mode b: arbitary subelements */
// TODO: check whether returned children array are retained!
children = [_element hasChildNodes]
? [_b buildNodes:[_element childNodes] templateBuilder:_b]
: (NSArray *)nil;
}
/* build associations */
if ((assocs = [_b associationsForAttributes:[_element attributes]]) == nil)
assocs = [NSMutableDictionary dictionaryWithCapacity:2];
/* fill in missing default associations */
if ([assocs objectForKey:@"onClose"] == nil) {
tmp = [WOAssociation associationWithKeyPath:
@"existingSession.navigation.leavePage"];
[assocs setObject:tmp forKey:@"onClose"];
}
if ([assocs objectForKey:@"title"] == nil) {
tmp = [WOAssociation associationWithKeyPath:@"labels.$name"];
[assocs setObject:tmp forKey:@"title"];
}
/* build window */
if (debugOn) [self debugWithFormat:@" window assocs: %@", assocs];
window = [[[self windowFrameClass] alloc] initWithName:@"win"
associations:assocs
contentElements:children];
frameChildren = [NSArray arrayWithObjects:&window count:1];
[window release]; window = nil;
/* create component */
if (debugOn) [self debugWithFormat:@"frame children: %@", frameChildren];
[_b registerSubComponentWithId:cid
componentName:[self frameComponentName] bindings:nil];
return [[ChildRefClass alloc]
initWithName:cid associations:nil contentElements:frameChildren];
}
- (WOElement *)buildSpan:(id)_element templateBuilder:(id)_b {
NSMutableArray *ma;
NSArray *children;
WOElement *element;
children = [_element hasChildNodes]
? [_b buildNodes:[_element childNodes] templateBuilder:_b]
: (NSArray *)nil;
ma = [[NSMutableArray alloc] initWithCapacity:[children count] + 3];
[ma addObject:@""]; // TODO: add CSS class
if (children != nil) [ma addObjectsFromArray:children];
[ma addObject:@" "];
element = [self elementForElementsAndStrings:ma];
[ma release];
return element;
}
- (WOElement *)buildContainer:(id)_element templateBuilder:(id)_b {
// this is a 'noop' tag, which only generates its children, useful for
// as a roottag for templates
NSArray *children;
children = [_element hasChildNodes]
? [_b buildNodes:[_element childNodes] templateBuilder:_b]
: (NSArray *)nil;
return [self elementForElementsAndStrings:children];
}
- (WOElement *)buildLabel:(id)_elem templateBuilder:(id)_b {
/*
key > value // always keypath: labels.$key
*/
NSMutableDictionary *associations;
WOElement *element;
NSString *kp;
kp = [_elem attribute:@"key" namespaceURI:@"*"];
if ([kp length] == 0) {
[self logWithFormat:@"WARNING: missing 'key' attribute in tag: %@", _elem];
kp = @"missing label key";
}
kp = [@"labels." stringByAppendingString:kp];
associations = [[NSMutableDictionary alloc] initWithCapacity:2];
[associations setObject:[WOAssociation associationWithKeyPath:kp]
forKey:@"value"];
element = [[DynStrClass alloc] initWithName:nil associations:associations
contentElements:nil];
[associations release];
return element;
}
- (WOElement *)buildFont:(id)_element templateBuilder:(id)_b {
return [self wrapChildrenOfElement:_element
inElementOfClass:[self fontClass]
templateBuilder:_b];
}
- (WOElement *)buildEditFont:(id)_element templateBuilder:(id)_b {
return [self wrapChildrenOfElement:_element
inElementOfClass:[self editFontClass]
templateBuilder:_b];
}
- (WOElement *)buildCalendarPopUp:(id)_el templateBuilder:(id)_b {
/*
name // always constant
formName // always constant [default: 'editform']
CalendarPopupStartDateLink: SkyCalendarPopUp { // WOComponent!
elementName = "startDate";
formName = "editform";
}
*/
NSMutableDictionary *assocs;
NSString *s;
NSString *cid;
cid = [_b uniqueIDForNode:_el];
if (debugOn) [self debugWithFormat:@" calpopup CID: %@", cid];
/* setup associations */
assocs = [[NSMutableDictionary alloc] initWithCapacity:4];
if ((s = [_el attribute:@"name" namespaceURI:@"*"]) != nil) {
[assocs setObject:[WOAssociation associationWithValue:s]
forKey:@"elementName"];
}
else
[self logWithFormat:@"ERROR: missing 'name' attribute on tag: %@", _el];
if ((s = [_el attribute:@"formName" namespaceURI:@"*"]) == nil)
s = @"editform";
[assocs setObject:[WOAssociation associationWithValue:s]
forKey:@"formName"];
/* build component */
[_b registerSubComponentWithId:cid
componentName:[self calPopUpComponentName] bindings:assocs];
[assocs release]; assocs = nil;
return [[ChildRefClass alloc]
initWithName:cid associations:nil contentElements:nil];
}
- (WOElement *)buildListView:(id)_el templateBuilder:(id)_b {
/*
ParticipantList: SkyListView {
list = participants;
item = item;
columns = noOfCols;
selectInverse = YES;
selectedItems = removedParticipants;
attributes = attributesList;
}
*/
NSMutableDictionary *assocs;
NSString *cid;
cid = [_b uniqueIDForNode:_el];
if (debugOn) [self debugWithFormat:@" listview CID: %@", cid];
/* build associations */
if ((assocs = [_b associationsForAttributes:[_el attributes]]) == nil)
assocs = [NSMutableDictionary dictionaryWithCapacity:2];
#if 0
[self logWithFormat:@"CID %@ ASSOCS: %@", cid, assocs];
#endif
/* build component */
[_b registerSubComponentWithId:cid
componentName:[self listViewComponentName] bindings:assocs];
return [[ChildRefClass alloc]
initWithName:cid associations:nil contentElements:nil];
}
/* element class builder (direct mappings of XML tag to dynamic element) */
- (Class)classForElement:(id)_element {
NSString *tagName;
unsigned tl;
unichar c1;
if (![[_element namespaceURI] isEqualToString:XMLNS_OGoWOx])
return [super classForElement:_element];
tagName = [_element tagName];
if ((tl = [tagName length]) < 2)
return Nil;
c1 = [tagName characterAtIndex:0];
switch (c1) {
case 't': /* starting with 't' */
if (tl == 7 && [tagName isEqualToString:@"td-attr"])
return NSClassFromString(@"SkyAttributeCell");
if (tl == 8 && [tagName isEqualToString:@"td-value"])
return NSClassFromString(@"SkyValueCell");
break;
}
return [super classForElement:_element];
}
/* main build dispatcher */
- (WOElement *)buildElement:(id)_element templateBuilder:(id)_b {
NSString *tagName;
unsigned tl;
unichar c1;
WOElement *element;
if (![[_element namespaceURI] isEqualToString:XMLNS_OGoWOx])
return [self->nextBuilder buildElement:_element templateBuilder:_b];
tagName = [_element tagName];
if ((tl = [tagName length]) < 2)
return nil;
c1 = [tagName characterAtIndex:0];
if (debugOn) [self debugWithFormat:@"try to build OGo tag: %@", tagName];
element = nil;
switch (c1) {
case 'a':
if (tl == 10 && [tagName isEqualToString:@"attributes"])
element = [self buildAttributes:_element templateBuilder:_b];
if (tl == 9 && [tagName isEqualToString:@"attribute"])
element = [self buildAttribute:_element templateBuilder:_b];
break;
case 'b':
if (tl == 7 && [tagName isEqualToString:@"buttons"])
element = [self buildButtonRow:_element templateBuilder:_b];
break;
case 'c':
if (tl == 13 && [tagName isEqualToString:@"calendarpopup"])
element = [self buildCalendarPopUp:_element templateBuilder:_b];
if (tl == 9 && [tagName isEqualToString:@"container"])
element = [self buildContainer:_element templateBuilder:_b];
break;
case 'e':
if (tl == 8 && [tagName isEqualToString:@"editfont"])
element = [self buildEditFont:_element templateBuilder:_b];
break;
case 'f':
if (tl == 4 && [tagName isEqualToString:@"font"])
element = [self buildFont:_element templateBuilder:_b];
break;
case 'l':
if (tl == 5 && [tagName isEqualToString:@"label"])
element = [self buildLabel:_element templateBuilder:_b];
if (tl == 8 && [tagName isEqualToString:@"listview"])
element = [self buildListView:_element templateBuilder:_b];
break;
case 'o':
if (tl == 11 && [tagName isEqualToString:@"objectvalue"])
element = [self buildObjectValue:_element templateBuilder:_b];
break;
case 'p':
if (tl == 4 && [tagName isEqualToString:@"page"])
element = [self buildPage:_element templateBuilder:_b];
if (tl == 9 && [tagName isEqualToString:@"page-head"])
element = [self buildPageHead:_element templateBuilder:_b];
if (tl == 9 && [tagName isEqualToString:@"page-body"])
element = [self buildPageBody:_element templateBuilder:_b];
break;
case 's':
if (tl == 4 && [tagName isEqualToString:@"span"])
element = [self buildSpan:_element templateBuilder:_b];
break;
case 't':
if (tl == 3 && [tagName isEqualToString:@"tab"])
element = [self buildTab:_element templateBuilder:_b];
if (tl == 7 && [tagName isEqualToString:@"tabitem"])
element = [self buildTabItem:_element templateBuilder:_b];
if (tl == 7 && [tagName isEqualToString:@"td-attr"])
return [super buildElement:_element templateBuilder:_b];
if (tl == 8 && [tagName isEqualToString:@"td-value"])
return [super buildElement:_element templateBuilder:_b];
break;
}
if (element == nil) {
if (debugOn)
[self logWithFormat:@"WARNING: could not build OGo tag: '%@'", tagName];
/* we need to call super, so that the build queue processing continues */
return [super buildElement:_element templateBuilder:_b];
}
return element;
}
/* debugging */
- (BOOL)isDebuggingEnabled {
return debugOn;
}
@end /* OGoElemBuilder */