]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOCompoundElement.m
added some WebDrive WebDAV properties
[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%08X: i[%i] %s <%s>: %0.3fs\n",
265                  (unsigned int)self,
266                  i, [[_ctx elementID] cString],
267                  [child class]->name,
268                  diff);
269         }
270       }
271       if (logId) {
272         NSLog(@"WOCompoundElement: pool will release ... (lastId=%@)",
273               [_ctx elementID]);
274       }
275       [pool release];
276 #endif
277
278       if (descriptiveIDs) {
279         [_ctx deleteLastElementIDComponent];
280         [_ctx appendElementIDComponent:
281                 [NSString stringWithFormat:@"c%i", i]];
282       }
283       else
284         incId(_ctx, @selector(incrementLastElementIDComponent));
285     }
286     [_ctx deleteLastElementIDComponent];
287
288 #if DEBUG
289     if (profElements) {
290       NSTimeInterval diff;
291       int i;
292       diff = [[NSDateClass date] timeIntervalSince1970] - st;
293 #if 1
294       for (i = [_ctx componentStackCount] + depth; i >= 0; i--)
295         printf("  ");
296 #endif
297       printf("CompoundElem0x%08X(#%i) %s (component=%s): %0.3fs\n",
298              (unsigned int)self,
299              self->count,
300              [[_ctx elementID] cString],
301              [[(WOComponent *)[_ctx component] name] cString],
302              diff);
303     }
304 #endif
305     
306 #if defined(DEBUG) && USE_EXCEPTION_HANDLER
307   }
308   NS_HANDLER {
309     NSMutableDictionary *ui;
310     id tmp;
311     
312     ui = [[localException userInfo] mutableCopy];
313     if (ui == nil) ui = [[NSMutableDictionary alloc] init];
314     
315     if ((tmp = [ui objectForKey:cName]) == nil)
316       [ui setObject:[[_ctx component] name] forKey:cName];
317     if ((tmp = [ui objectForKey:elemId]) == nil)
318       [ui setObject:[_ctx elementID] forKey:elemId];
319
320     [localException setUserInfo:ui];
321     [ui release]; ui = nil;
322     
323     [localException raise];
324   }
325   NS_ENDHANDLER;
326 #endif
327
328   depth--;
329 }
330
331 /* description */
332
333 - (NSString *)associationDescription {
334   NSMutableString *str = [NSMutableString stringWithCapacity:256];
335   int i;
336
337   [str appendString:@"children=\n"];
338   for (i = 0; i < self->count; i++) {
339     [str appendString:@"  "];
340     [str appendString:[self->children[i] description]];
341     [str appendString:@"\n"];
342   }
343   return str;
344 }
345
346 @end /* WOCompoundElement */
347
348 @implementation WOHTMLStaticGroup
349
350 /* this element was discovered in SSLContainer.h and may not be public */
351
352 @end /* WOHTMLStaticGroup */