2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 // $Id: WODynamicElement.m 1 2004-08-20 10:08:27Z znek $
23 #include <NGObjWeb/WODynamicElement.h>
24 #include "WOElement+private.h"
25 #include "WOCompoundElement.h"
26 #include <NGObjWeb/WOApplication.h>
29 typedef struct _WOExtraAttrItem {
32 NSString *(*valQuery)(id,SEL,WOComponent *c);
35 typedef struct _WOExtraAttrStruct {
36 WOExtraAttrItem *items;
37 NSString *extraString;
41 @implementation WODynamicElement
44 return [super version] + 0 /* v2 */;
47 static Class FormClass = Nil;
48 static Class FormElementClass = Nil;
51 static BOOL isInitialized = NO;
53 NSAssert2([super version] == 2,
54 @"invalid superclass (%@) version %i !",
55 NSStringFromClass([self superclass]), [super version]);
60 FormClass = NSClassFromString(@"WOForm");
61 FormElementClass = NSClassFromString(@"WOInput");
67 - (id)initWithName:(NSString *)_name
68 associations:(NSDictionary *)_associations
69 template:(WOElement *)_rootChild
71 if ((self = [super init])) {
74 self->otherTagString = OWGetProperty(_associations, @"otherTagString");
76 t = OWGetProperty(_associations, @"debug");
77 self->debug = [t boolValueInComponent:nil];
82 - (id)initWithName:(NSString *)_name
83 associations:(NSDictionary *)_associations
84 contentElements:(NSArray *)_contents
86 /* this method was discovered in SSLContainer.h and may not be public */
87 WOCompoundElement *template;
90 count = [_contents count];
95 else if (count == 1) {
96 template = [_contents objectAtIndex:0];
99 template = [[WOCompoundElement allocForCount:[_contents count]
101 initWithContentElements:_contents];
104 return [self initWithName:_name
105 associations:_associations
110 return [self initWithName:[NSString stringWithFormat:@"0x%08X", self]
116 register WOExtraAttrs *ea;
118 [self->otherTagString release];
120 if ((ea = self->extraAttributes) != NULL) { // GC
121 register unsigned short i;
123 [ea->extraString release];
124 for (i = 0; i < ea->count; i++) {
125 [ea->items[i].key release];
126 [ea->items[i].value release];
131 free(self->extraAttributes);
132 self->extraAttributes = ea = NULL;
139 - (NSString *)elementID {
140 return [[[WOApplication application] context] elementID];
143 - (void)setExtraAttributes:(NSDictionary *)_extras {
144 register WOExtraAttrs *ea;
149 if ([_extras count] == 0)
150 /* no extra attributes ... */
153 if (self->extraAttributes) {
154 NSLog(@"ERROR(%s): tried to reset extra attributes (access denied) !!!",
155 __PRETTY_FUNCTION__);
159 /* setup structure */
161 ea = calloc(1, sizeof(WOExtraAttrs));
163 ea->items = calloc([_extras count], sizeof(WOExtraAttrItem));
168 ke = [_extras keyEnumerator];
169 while ((key = [ke nextObject])) {
170 WOAssociation *value;
172 //key = [key lowercaseString];
173 value = [_extras objectForKey:key];
175 if ([value isValueConstant]) {
176 /* static value (calculated *now*) */
180 es = [[NSMutableString alloc] initWithCapacity:128];
183 s = [value stringValueInComponent:nil];
185 /* HTML escape value ... */
186 s = [s stringByEscapingHTMLAttributeValue];
188 /* add to static string */
189 [es appendString:@" "];
190 [es appendString:key];
191 [es appendString:@"=\""];
193 [es appendString:@"\""];
196 /* dynamic value (calculated at runtime) */
197 register WOExtraAttrItem *item;
199 item = &(ea->items[ea->count]);
200 item->key = [key copy];
201 item->value = RETAIN(value);
202 item->valQuery = /* cache method IMP */
203 (void*)[value methodForSelector:@selector(stringValueInComponent:)];
208 /* check results for static vs dynamic ... */
210 if (ea->count == 0) {
211 /* no dynamic attributes, free items structure ... */
215 if ([es length] > 0) ea->extraString = [es copy];
216 [es release]; es = nil;
219 self->extraAttributes = ea;
222 - (WOElement *)template {
226 + (BOOL)isDynamicElement {
232 - (void)appendExtraAttributesToResponse:(WOResponse *)_response
233 inContext:(WOContext *)_ctx
235 if (self->extraAttributes) {
236 register WOExtraAttrs *ea;
238 ea = self->extraAttributes;
241 /* has dynamic attributes */
242 WOComponent *sComponent;
243 register unsigned short i;
245 sComponent = [_ctx component];
247 for (i = 0; i < ea->count; i++) {
248 register WOExtraAttrItem *item;
251 item = &(ea->items[i]);
253 if (item->valQuery) {
254 /* use cached selector implementation */
255 value = item->valQuery(item->value,@selector(stringValueInComponent:),
259 value = [item->value stringValueInComponent:sComponent];
262 WOResponse_AddChar(_response, ' ');
263 WOResponse_AddString(_response, item->key);
264 WOResponse_AddCString(_response, "=\"");
265 [_response appendContentHTMLAttributeValue:value];
266 WOResponse_AddChar(_response, '"');
270 /* add static string */
272 WOResponse_AddString(_response, ea->extraString);
276 - (NSString *)associationDescription {
280 if (self->extraAttributes) {
285 ad = [NSMutableString stringWithCapacity:32];
286 keys = [self->extraAttributes keyEnumerator];
287 while ((key = [keys nextObject])) {
288 WOAssociation *value;
290 value = [self->extraAttributes objectForKey:key];
292 [ad appendString:@" "];
293 [ad appendString:key];
294 [ad appendString:@"="];
295 [ad appendString:[value description]];
304 - (NSString *)description {
305 NSMutableString *desc = [NSMutableString stringWithCapacity:100];
306 NSString *assocDesc = [self associationDescription];
308 [desc appendFormat:@"<%@[0x%08X]:", NSStringFromClass([self class]), self];
309 if (assocDesc) [desc appendString:assocDesc];
310 [desc appendString:@">"];
315 @end /* WODynamicElement */
317 #include <DOM/EDOM.h>
318 #include <NGObjWeb/NGObjWeb.h>
319 #include <NGObjWeb/WOxElemBuilder.h>
320 #include <SaxObjC/XMLNamespaces.h>
324 The new DOM element init function for elements constructed from DOM element
327 The default method is defined on NSObject instead of WOElement, since some
328 dynamic elements are class clusters, which use temporary non-WOElement
329 classes during construction.
331 The default construction process requires no support from existing NGObjWeb
333 It maps all tag attributes to element associations and all child nodes to
335 The tagname is used as the dynamic element name.
338 @implementation NSObject(InitElement)
340 - (id)initWithElement:(id<DOMElement>)_element
341 templateBuilder:(WOxElemBuilder *)_builder
344 NSMutableDictionary *assocs;
346 id<NSObject,DOMNamedNodeMap> attrs;
349 name = [_element tagName];
351 /* construct associations */
354 attrs = [_element attributes];
355 if ((count = [attrs length]) > 0)
356 assocs = [_builder associationsForAttributes:attrs];
358 /* construct child elements */
360 if ([_element hasChildNodes]) {
361 /* look for var:binding tags ... */
363 children = [_builder buildNodes:[_element childNodes]
364 templateBuilder:_builder];
369 /* construct self ... */
371 self = [(WODynamicElement *)self initWithName:name
373 contentElements:children];
374 [(id)self setExtraAttributes:assocs];
378 @end /* NSObject(InitElement) */