]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOCompoundElement.m
hotfix
[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 int embedInPool  = -1;
40 static int logId        = -1;
41 static Class NSDateClass = Nil;
42 #endif
43 static int descriptiveIDs = -1;
44
45 + (void)initialize {
46   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
47
48   if (descriptiveIDs == -1) {
49     descriptiveIDs =
50       [[ud objectForKey:@"WODescriptiveElementIDs"] boolValue] ? 1 : 0;
51   }
52
53 #if DEBUG
54   if (profElements == -1) {
55     profElements = [[[NSUserDefaults standardUserDefaults]
56                                      objectForKey:@"WOProfileElements"]
57                                      boolValue] ? 1 : 0;
58   }
59   if (embedInPool == -1) {
60     embedInPool = [[[NSUserDefaults standardUserDefaults]
61                                     objectForKey:@"WOCompoundElementPool"]
62                                     boolValue] ? 1 : 0;
63     NSLog(@"WOCompoundElement: pool embedding is on.");
64   }
65   if (logId == -1) {
66     logId = [[[NSUserDefaults standardUserDefaults]
67                               objectForKey:@"WOCompoundElementLogID"]
68                               boolValue] ? 1 : 0;
69     NSLog(@"WOCompoundElement: id logging is on.");
70   }
71 #endif
72 }
73
74 + (id)allocForCount:(int)_count zone:(NSZone *)_zone {
75   return NSAllocateObject(self, _count * sizeof(WOElement *), _zone);
76 }
77
78 - (id)initWithContentElements:(NSArray *)_children {
79   WOElement *(*objAtIdx)(id, SEL, int);
80   int i;
81   
82   if (_children == nil) {
83     NSLog(@"%@: invalid argument ..", self);
84     self = [self autorelease];
85     return nil;
86   }
87   
88   self = [super init];
89
90   objAtIdx = (void *)[_children methodForSelector:
91                                 @selector(objectAtIndex:)];
92   NSAssert1(objAtIdx != NULL,
93             @"could not get -objectAtIndex: method of %@",
94             _children);
95   
96   self->count = [_children count];
97   for (i = (self->count - 1); i >= 0; i--) {
98     register WOElement *child;
99     
100     child = objAtIdx(_children, @selector(objectAtIndex:), i);
101     
102     self->children[i] = [child retain];
103   }
104   return self;
105 }
106
107 - (id)initWithChildren:(NSArray *)_children {
108   return [self initWithContentElements:_children];
109 }
110 - (id)init {
111   return [self initWithContentElements:nil];
112 }
113
114 - (void)dealloc {
115   int i;
116   for (i = 0; i < self->count; i++) {
117     [self->children[i] release];
118     self->children[i] = nil;
119   }
120   [super dealloc];
121 }
122
123 /* accessors */
124
125 - (NSArray *)subelements {
126   if (self->count == 0)
127     return nil;
128
129   return [NSArray arrayWithObjects:self->children count:self->count];
130 }
131
132 /* responder */
133
134 - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
135   void (*incId)(id, SEL);
136   unsigned short i;
137
138   incId = (void *)
139     [_ctx methodForSelector:@selector(incrementLastElementIDComponent)];
140
141   if (descriptiveIDs)
142     [_ctx appendElementIDComponent:@"c0"];
143   else
144     [_ctx appendZeroElementIDComponent];
145   
146   for (i = 0; i < self->count; i++) {
147     register WOElement *child = self->children[i];
148     
149     if (child->takeValues) {
150       child->takeValues(child,
151                         @selector(takeValuesFromRequest:inContext:),
152                         _rq, _ctx);
153     }
154     else
155       [child takeValuesFromRequest:_rq inContext:_ctx];
156     
157     if (descriptiveIDs) {
158       [_ctx deleteLastElementIDComponent];
159       [_ctx appendElementIDComponent:
160               [NSString stringWithFormat:@"c%i", i]];
161     }
162     else
163       incId(_ctx, @selector(incrementLastElementIDComponent));
164   }
165   [_ctx deleteLastElementIDComponent];
166 }
167
168 - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
169   id result = nil;
170   id idxId;
171   
172   if ((idxId = [_ctx currentElementID])) {
173     int idx = [idxId intValue];
174
175     idx = (descriptiveIDs)
176       ? [[idxId substringFromIndex:1] intValue]
177       : [idxId intValue];
178     
179     [_ctx consumeElementID]; // consume index-id
180     
181     if ((idx < 0) || (idx >= self->count)) {
182       [[_ctx session] logWithFormat:
183                         @"%s: invalid element id, %i is out of range (0-%i) !",
184                         __PRETTY_FUNCTION__,
185                         idx, (self->count - 1)];
186       return nil;
187     }
188     
189     [_ctx appendElementIDComponent:idxId];
190     result = [self->children[idx] invokeActionForRequest:_rq inContext:_ctx];
191     [_ctx deleteLastElementIDComponent];
192   }
193   else {
194     [[_ctx session]
195            logWithFormat:@"%s: MISSING INDEX ID in URL: %@ !",
196              __PRETTY_FUNCTION__,
197              [_ctx senderID]];
198   }
199   return result;
200 }
201
202 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
203   static int depth = 0;
204   void (*incId)(id, SEL);
205   unsigned short i;
206 #if DEBUG
207 #if USE_EXCEPTION_HANDLER
208   static NSString *cName  = @"componentName";
209   static NSString *elemId = @"elementID";
210 #endif
211   NSTimeInterval st = 0.0;
212   
213   if (NSDateClass == Nil)
214     NSDateClass = [NSDate class];
215 #endif
216
217   depth++;
218   
219 #if defined(DEBUG) && USE_EXCEPTION_HANDLER
220   NS_DURING {
221 #endif
222
223 #ifdef DEBUG
224     if (profElements)
225       st = [[NSDateClass date] timeIntervalSince1970];
226 #endif
227     
228     incId = (void *)
229       [_ctx methodForSelector:@selector(incrementLastElementIDComponent)];
230     
231     if (descriptiveIDs)
232       [_ctx appendElementIDComponent:@"c0"];
233     else
234       [_ctx appendZeroElementIDComponent];
235     
236     for (i = 0; i < self->count; i++) {
237       register WOElement *child = self->children[i];
238 #if DEBUG
239       NSAutoreleasePool *pool = nil;
240       NSTimeInterval st = 0.0;
241       if (embedInPool) pool = [[NSAutoreleasePool alloc] init];
242       if (profElements)
243         st = [[NSDateClass date] timeIntervalSince1970];
244 #endif
245       
246       if (child->appendResponse) {
247         child->appendResponse(child,
248                               @selector(appendToResponse:inContext:),
249                               _response, _ctx);
250       }
251       else
252         [child appendToResponse:_response inContext:_ctx];
253       
254 #if DEBUG
255       if (profElements) {
256         NSTimeInterval diff;
257         int j;
258         diff = [[NSDateClass date] timeIntervalSince1970] - st;
259         if (diff > 0.0005) {
260 #if 1
261           for (j = [_ctx componentStackCount] + depth; j >= 0; j--)
262             printf("  ");
263 #endif
264           printf("  Child of 0x%p: i[%i] %s <%s>: %0.3fs\n",
265                  self, i, [[_ctx elementID] cString], [child class]->name,
266                  diff);
267         }
268       }
269       if (logId) {
270         NSLog(@"WOCompoundElement: pool will release ... (lastId=%@)",
271               [_ctx elementID]);
272       }
273       [pool release];
274 #endif
275
276       if (descriptiveIDs) {
277         [_ctx deleteLastElementIDComponent];
278         [_ctx appendElementIDComponent:
279                 [NSString stringWithFormat:@"c%i", i]];
280       }
281       else
282         incId(_ctx, @selector(incrementLastElementIDComponent));
283     }
284     [_ctx deleteLastElementIDComponent];
285
286 #if DEBUG
287     if (profElements) {
288       NSTimeInterval diff;
289       int i;
290       diff = [[NSDateClass date] timeIntervalSince1970] - st;
291 #if 1
292       for (i = [_ctx componentStackCount] + depth; i >= 0; i--)
293         printf("  ");
294 #endif
295       printf("CompoundElem0x%p(#%i) %s (component=%s): %0.3fs\n",
296              self, self->count, [[_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 */