]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOCompoundElement.m
started TAL element builder
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOCompoundElement.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21
22 #include "WOCompoundElement.h"
23 #include "WOElement+private.h"
24 #include <NGObjWeb/WOContext.h>
25 #include "decommon.h"
26
27 #if APPLE_RUNTIME || NeXT_RUNTIME
28 #  include <objc/objc-class.h>
29 #endif
30
31 @interface WOContext(ComponentStackCount)
32 - (unsigned)componentStackCount;
33 @end
34
35 @implementation WOCompoundElement
36
37 #ifdef DEBUG
38 static int profElements  = -1;
39 static Class NSDateClass = Nil;
40 #endif
41 static int descriptiveIDs = -1;
42
43 + (id)allocForCount:(int)_count zone:(NSZone *)_zone {
44   return NSAllocateObject(self, _count * sizeof(WOElement *), _zone);
45 }
46
47 - (id)initWithContentElements:(NSArray *)_children {
48   WOElement *(*objAtIdx)(id, SEL, int);
49   int i;
50   
51   if (_children == nil) {
52     NSLog(@"%@: invalid argument ..", self);
53     self = [self autorelease];
54     return nil;
55   }
56   
57   self = [super init];
58
59   if (descriptiveIDs == -1) {
60     descriptiveIDs =
61       [[[NSUserDefaults standardUserDefaults]
62                         objectForKey:@"WODescriptiveElementIDs"]
63                         boolValue] ? 1 : 0;
64   }
65   
66   objAtIdx = (void *)[_children methodForSelector:
67                                 @selector(objectAtIndex:)];
68   NSAssert1(objAtIdx != NULL,
69             @"could not get -objectAtIndex: method of %@",
70             _children);
71   
72   self->count = [_children count];
73   for (i = (self->count - 1); i >= 0; i--) {
74     register WOElement *child;
75     
76     child = objAtIdx(_children, @selector(objectAtIndex:), i);
77     
78     self->children[i] = [child retain];
79   }
80   return self;
81 }
82
83 - (id)initWithChildren:(NSArray *)_children {
84   return [self initWithContentElements:_children];
85 }
86 - (id)init {
87   return [self initWithContentElements:nil];
88 }
89
90 - (void)dealloc {
91   int i;
92   for (i = 0; i < self->count; i++) {
93     [self->children[i] release];
94     self->children[i] = nil;
95   }
96   [super dealloc];
97 }
98
99 /* accessors */
100
101 - (NSArray *)subelements {
102   if (self->count == 0)
103     return nil;
104
105   return [NSArray arrayWithObjects:self->children count:self->count];
106 }
107
108 /* responder */
109
110 - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
111   void (*incId)(id, SEL);
112   unsigned short i;
113
114   incId = (void *)
115     [_ctx methodForSelector:@selector(incrementLastElementIDComponent)];
116
117   if (descriptiveIDs)
118     [_ctx appendElementIDComponent:@"c0"];
119   else
120     [_ctx appendZeroElementIDComponent];
121   
122   for (i = 0; i < self->count; i++) {
123     register WOElement *child = self->children[i];
124     
125     if (child->takeValues) {
126       child->takeValues(child,
127                         @selector(takeValuesFromRequest:inContext:),
128                         _rq, _ctx);
129     }
130     else
131       [child takeValuesFromRequest:_rq inContext:_ctx];
132     
133     if (descriptiveIDs) {
134       [_ctx deleteLastElementIDComponent];
135       [_ctx appendElementIDComponent:
136               [NSString stringWithFormat:@"c%i", i]];
137     }
138     else
139       incId(_ctx, @selector(incrementLastElementIDComponent));
140   }
141   [_ctx deleteLastElementIDComponent];
142 }
143
144 - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
145   id result = nil;
146   id idxId;
147   
148   if ((idxId = [_ctx currentElementID])) {
149     int idx = [idxId intValue];
150
151     idx = (descriptiveIDs)
152       ? [[idxId substringFromIndex:1] intValue]
153       : [idxId intValue];
154     
155     [_ctx consumeElementID]; // consume index-id
156     
157     if ((idx < 0) || (idx >= self->count)) {
158       [[_ctx session] logWithFormat:
159                         @"%s: invalid element id, %i is out of range (0-%i) !",
160                         __PRETTY_FUNCTION__,
161                         idx, (self->count - 1)];
162       return nil;
163     }
164     
165     [_ctx appendElementIDComponent:idxId];
166     result = [self->children[idx] invokeActionForRequest:_rq inContext:_ctx];
167     [_ctx deleteLastElementIDComponent];
168   }
169   else {
170     [[_ctx session]
171            logWithFormat:@"%s: MISSING INDEX ID in URL: %@ !",
172              __PRETTY_FUNCTION__,
173              [_ctx senderID]];
174   }
175   return result;
176 }
177
178 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
179   static int depth = 0;
180   void (*incId)(id, SEL);
181   unsigned short i;
182 #if DEBUG
183 #if USE_EXCEPTION_HANDLER
184   static NSString *cName  = @"componentName";
185   static NSString *elemId = @"elementID";
186 #endif
187   static int embedInPool = -1;
188   static int logId = -1;
189   NSTimeInterval st = 0.0;
190
191   if (NSDateClass == Nil)
192     NSDateClass = [NSDate class];
193   
194   if (profElements == -1) {
195     profElements = [[[NSUserDefaults standardUserDefaults]
196                                      objectForKey:@"WOProfileElements"]
197                                      boolValue] ? 1 : 0;
198   }
199   if (embedInPool == -1) {
200     embedInPool = [[[NSUserDefaults standardUserDefaults]
201                                     objectForKey:@"WOCompoundElementPool"]
202                                     boolValue] ? 1 : 0;
203     NSLog(@"WOCompoundElement: pool embedding is on.");
204   }
205   if (logId == -1) {
206     logId = [[[NSUserDefaults standardUserDefaults]
207                               objectForKey:@"WOCompoundElementLogID"]
208                               boolValue] ? 1 : 0;
209     NSLog(@"WOCompoundElement: id logging is on.");
210   }
211 #endif
212
213   depth++;
214   
215 #if defined(DEBUG) && USE_EXCEPTION_HANDLER
216   NS_DURING {
217 #endif
218
219 #ifdef DEBUG
220     if (profElements)
221       st = [[NSDateClass date] timeIntervalSince1970];
222 #endif
223     
224     incId = (void *)
225       [_ctx methodForSelector:@selector(incrementLastElementIDComponent)];
226     
227     if (descriptiveIDs)
228       [_ctx appendElementIDComponent:@"c0"];
229     else
230       [_ctx appendZeroElementIDComponent];
231     
232     for (i = 0; i < self->count; i++) {
233       register WOElement *child = self->children[i];
234 #if DEBUG
235       NSAutoreleasePool *pool = nil;
236       NSTimeInterval st = 0.0;
237       if (embedInPool) pool = [[NSAutoreleasePool alloc] init];
238       if (profElements)
239         st = [[NSDateClass date] timeIntervalSince1970];
240 #endif
241       
242       if (child->appendResponse) {
243         child->appendResponse(child,
244                               @selector(appendToResponse:inContext:),
245                               _response, _ctx);
246       }
247       else
248         [child appendToResponse:_response inContext:_ctx];
249       
250 #if DEBUG
251       if (profElements) {
252         NSTimeInterval diff;
253         int j;
254         diff = [[NSDateClass date] timeIntervalSince1970] - st;
255         if (diff > 0.0005) {
256 #if 1
257           for (j = [_ctx componentStackCount] + depth; j >= 0; j--)
258             printf("  ");
259 #endif
260           printf("  Child of 0x%08X: i[%i] %s <%s>: %0.3fs\n",
261                  (unsigned int)self,
262                  i, [[_ctx elementID] cString],
263                  [child class]->name,
264                  diff);
265         }
266       }
267       if (logId) {
268         NSLog(@"WOCompoundElement: pool will release ... (lastId=%@)",
269               [_ctx elementID]);
270       }
271       [pool release];
272 #endif
273
274       if (descriptiveIDs) {
275         [_ctx deleteLastElementIDComponent];
276         [_ctx appendElementIDComponent:
277                 [NSString stringWithFormat:@"c%i", i]];
278       }
279       else
280         incId(_ctx, @selector(incrementLastElementIDComponent));
281     }
282     [_ctx deleteLastElementIDComponent];
283
284 #if DEBUG
285     if (profElements) {
286       NSTimeInterval diff;
287       int i;
288       diff = [[NSDateClass date] timeIntervalSince1970] - st;
289 #if 1
290       for (i = [_ctx componentStackCount] + depth; i >= 0; i--)
291         printf("  ");
292 #endif
293       printf("CompoundElem0x%08X(#%i) %s (component=%s): %0.3fs\n",
294              (unsigned int)self,
295              self->count,
296              [[_ctx elementID] cString],
297              [[(WOComponent *)[_ctx component] name] cString],
298              diff);
299     }
300 #endif
301     
302 #if defined(DEBUG) && USE_EXCEPTION_HANDLER
303   }
304   NS_HANDLER {
305     NSMutableDictionary *ui;
306     id tmp;
307     
308     ui = [[localException userInfo] mutableCopy];
309     if (ui == nil) ui = [[NSMutableDictionary alloc] init];
310     
311     if ((tmp = [ui objectForKey:cName]) == nil)
312       [ui setObject:[[_ctx component] name] forKey:cName];
313     if ((tmp = [ui objectForKey:elemId]) == nil)
314       [ui setObject:[_ctx elementID] forKey:elemId];
315
316     [localException setUserInfo:ui];
317     [ui release]; ui = nil;
318     
319     [localException raise];
320   }
321   NS_ENDHANDLER;
322 #endif
323
324   depth--;
325 }
326
327 /* description */
328
329 - (NSString *)associationDescription {
330   NSMutableString *str = [NSMutableString stringWithCapacity:256];
331   int i;
332
333   [str appendString:@"children=\n"];
334   for (i = 0; i < self->count; i++) {
335     [str appendString:@"  "];
336     [str appendString:[self->children[i] description]];
337     [str appendString:@"\n"];
338   }
339   return str;
340 }
341
342 @end /* WOCompoundElement */
343
344 @implementation WOHTMLStaticGroup
345
346 /* this element was discovered in SSLContainer.h and may not be public */
347
348 @end /* WOHTMLStaticGroup */