2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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 SOPE 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 SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include <NGObjWeb/WODynamicElement.h>
23 #include "WOElement+private.h"
24 #include "WOCompoundElement.h"
25 #include <NGObjWeb/WOApplication.h>
28 typedef struct _WOExtraAttrItem {
31 NSString *(*valQuery)(id,SEL,WOComponent *c);
34 typedef struct _WOExtraAttrStruct {
35 WOExtraAttrItem *items;
36 NSString *extraString;
40 @implementation WODynamicElement
43 return [super version] + 0 /* v2 */;
46 static Class FormClass = Nil;
47 static Class FormElementClass = Nil;
50 static BOOL isInitialized = NO;
52 NSAssert2([super version] == 2,
53 @"invalid superclass (%@) version %i !",
54 NSStringFromClass([self superclass]), [super version]);
59 FormClass = NSClassFromString(@"WOForm");
60 FormElementClass = NSClassFromString(@"WOInput");
66 - (id)initWithName:(NSString *)_name
67 associations:(NSDictionary *)_associations
68 template:(WOElement *)_rootChild
70 if ((self = [super init])) {
73 self->otherTagString = OWGetProperty(_associations, @"otherTagString");
75 t = OWGetProperty(_associations, @"debug");
76 self->debug = [t boolValueInComponent:nil];
81 - (id)initWithName:(NSString *)_name
82 associations:(NSDictionary *)_associations
83 contentElements:(NSArray *)_contents
85 /* this method was discovered in SSLContainer.h and may not be public */
86 WOCompoundElement *template;
89 count = [_contents count];
94 else if (count == 1) {
95 template = [_contents objectAtIndex:0];
98 template = [[WOCompoundElement allocForCount:[_contents count]
100 initWithContentElements:_contents];
103 return [self initWithName:_name
104 associations:_associations
109 return [self initWithName:[NSString stringWithFormat:@"0x%p", self]
115 register WOExtraAttrs *ea;
117 [self->otherTagString release];
119 if ((ea = self->extraAttributes) != NULL) { // GC
120 register unsigned short i;
122 [ea->extraString release];
123 for (i = 0; i < ea->count; i++) {
124 [ea->items[i].key release];
125 [ea->items[i].value release];
130 free(self->extraAttributes);
131 self->extraAttributes = ea = NULL;
138 - (NSString *)elementID {
139 return [[[WOApplication application] context] elementID];
142 - (void)setExtraAttributes:(NSDictionary *)_extras {
143 register WOExtraAttrs *ea;
148 if ([_extras count] == 0)
149 /* no extra attributes ... */
152 if (self->extraAttributes) {
153 [self errorWithFormat:
154 @"(%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;
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%p]:", 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) */