]> err.no Git - sope/blob - Recycler/NGObjDOM/WORenderDOM.m
fixed a warning
[sope] / Recycler / NGObjDOM / WORenderDOM.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include <NGObjDOM/WORenderDOM.h>
24 #include "ODNodeRenderer.h"
25 #include "common.h"
26
27 //#define DEBUG_DOM
28
29 #if NeXT_RUNTIME || APPLE_RUNTIME
30 #  define sel_get_name sel_getName
31 #endif
32
33 @interface WOContext(Privates)
34 - (unsigned)componentStackCount;
35 - (id)activeFormElement;
36 @end
37
38 @implementation WORenderDOM
39
40 static int profileComponents = -1;
41 static Class NSDateClass = Nil;
42
43 + (void)initialize {
44   if (NSDateClass == Nil)
45     NSDateClass = [NSDate class];
46   if (profileComponents == -1) {
47     profileComponents = [[[NSUserDefaults standardUserDefaults]
48                                           objectForKey:@"WOProfileComponents"]
49                                           boolValue] ? 1 : 0;
50   }
51 }
52
53 - (id)initWithName:(NSString *)_name
54   associations:(NSDictionary *)_assocs
55   template:(WOElement *)_templ
56 {
57   if ((self = [super initWithName:_name associations:nil template:nil])){
58     if (_templ)
59       NSLog(@"WARNING(%s): contains template !", __PRETTY_FUNCTION__);
60     
61     self->domDocument = [[_assocs objectForKey:@"domDocument"] copy];
62     self->node        = [[_assocs objectForKey:@"node"]        copy];
63     self->renderer    = [[_assocs objectForKey:@"renderer"]    copy];
64     self->factory     = [[_assocs objectForKey:@"factory"]     copy];
65   }
66   return self;
67 }
68
69 - (void)dealloc {
70   RELEASE(self->factory);
71   RELEASE(self->node);
72   RELEASE(self->renderer);
73   RELEASE(self->domDocument);
74   [super dealloc];
75 }
76
77 /* discovering renders */
78
79 - (ODNodeRenderer *)rendererForNode:(id)_domNode inContext:(WOContext *)_ctx {
80   ODNodeRenderer *lrenderer;
81   
82   if ([self->node isValueSettable])
83     [self->node setValue:_domNode inComponent:[_ctx component]];
84
85   if (self->factory) {
86     id<ODNodeRendererFactory> lfactory;
87
88     if ((lfactory = [self->factory valueInComponent:[_ctx component]])) {
89 #if DEBUG && 0
90       NSLog(@"factory: %@", lfactory);
91 #endif
92       lrenderer = [lfactory rendererForNode:_domNode inContext:_ctx];
93     }
94     else
95       lrenderer = nil;
96   }
97   else if (self->renderer)
98     lrenderer = [self->renderer valueInComponent:[_ctx component]];
99   else
100     lrenderer = nil;
101
102 #if DEBUG && 0
103   NSLog(@"lrenderer: %@", lrenderer);
104 #endif
105   
106   return lrenderer;
107 }
108
109 /* root level methods */
110
111 - (id)pushToCtx:(WOContext *)_ctx {
112   id old;
113
114   old = [_ctx objectForKey:@"domRenderFactory"];
115   [_ctx setObject:self forKey:@"domRenderFactory"];
116   return old;
117 }
118 - (void)popFromCtx:(WOContext *)_ctx old:(id)_old {
119   if (_old)
120     [_ctx setObject:_old forKey:@"domRenderFactory"];
121   else
122     [_ctx removeObjectForKey:@"domRenderFactory"];
123 }
124
125 - (BOOL)_requiresFormInContext:(WOContext *)_ctx
126   node:(id)_domNode
127   renderer:(id)_renderer
128 {
129   if ([_ctx isInForm])
130     return NO;
131   
132   return [_renderer requiresFormForNode:_domNode inContext:_ctx];
133 }
134
135 - (id)domInContext:(WOContext *)_ctx {
136   return [self->domDocument valueInComponent:[_ctx component]];
137 }
138
139 - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
140   ODNodeRenderer *lrenderer;
141   id   edom;
142   id   old;
143   BOOL doForm;
144   NSTimeInterval st = 0.0;
145
146   if (profileComponents)
147     st = [[NSDateClass date] timeIntervalSince1970];
148   
149 #if DEBUG
150   if ([_ctx isInForm]) {
151     NSLog(@"WARNING(%s): this element shouldn't be used in forms, it generates "
152           @"it's own one.", __PRETTY_FUNCTION__);
153   }
154 #endif
155
156   if ((edom = [self domInContext:_ctx]) == nil)
157     return;
158   
159   old = [self pushToCtx:_ctx];
160   
161   lrenderer = [self rendererForNode:edom inContext:_ctx];
162   doForm = [self _requiresFormInContext:_ctx node:edom renderer:lrenderer];
163
164   if (doForm) {
165     [_ctx setInForm:YES];
166   }
167   
168   [lrenderer takeValuesForNode:edom
169              fromRequest:_request
170              inContext:_ctx];
171
172   if (doForm) {
173     [_ctx setInForm:NO];
174   }
175   
176   [self popFromCtx:_ctx old:old];
177   
178   if (profileComponents) {
179     NSTimeInterval diff;
180     int i;
181     diff = [[NSDateClass date] timeIntervalSince1970] - st;
182     for (i = [_ctx componentStackCount]; i >= 0; i--)
183       printf("  ");
184     printf("[%s %s]: %0.3fs\n",
185            "WORenderDOM", sel_get_name(_cmd), diff);
186   }
187 }
188
189 - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
190   ODNodeRenderer *lrenderer;
191   id   result;
192   id   edom;
193   id   old;
194   BOOL doForm;
195   NSTimeInterval st = 0.0;
196
197   if (profileComponents)
198     st = [[NSDateClass date] timeIntervalSince1970];
199
200 #if DEBUG
201   if ([_ctx isInForm]) {
202     NSLog(@"WARNING(%s): this element shouldn't be used in forms, it generates "
203           @"it's own one.", __PRETTY_FUNCTION__);
204   }
205 #endif
206   
207   if ((edom = [self domInContext:_ctx]) == nil)
208     /* no DOM tree available */
209     return nil;
210   
211   old = [self pushToCtx:_ctx];
212   
213   lrenderer = [self rendererForNode:edom inContext:_ctx];
214   doForm    = [self _requiresFormInContext:_ctx node:edom renderer:lrenderer];
215   
216   if (doForm) {
217     [_ctx setInForm:YES];
218     
219     if ([_ctx currentElementID] == nil) {
220       id activeNode;
221       
222       activeNode = [_ctx activeFormElement];
223       
224       lrenderer = [self rendererForNode:activeNode inContext:_ctx];
225
226       result = [lrenderer invokeActionForNode:activeNode
227                           fromRequest:_request
228                           inContext:_ctx];
229     }
230     else {
231       result = [lrenderer invokeActionForNode:edom
232                           fromRequest:_request
233                           inContext:_ctx];
234     }
235     
236     [_ctx setInForm:NO];
237   }
238   else {
239     result = [lrenderer invokeActionForNode:edom
240                         fromRequest:_request
241                         inContext:_ctx];
242   }
243   
244   [self popFromCtx:_ctx old:old];
245   
246   if (profileComponents) {
247     NSTimeInterval diff;
248     int i;
249     diff = [[NSDateClass date] timeIntervalSince1970] - st;
250     for (i = [_ctx componentStackCount]; i >= 0; i--)
251       printf("  ");
252     printf("[%s %s]: %0.3fs\n",
253            "WORenderDOM", sel_get_name(_cmd), diff);
254   }
255
256   return result;
257 }
258
259 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
260   ODNodeRenderer *lrenderer;
261   WOComponent    *cmp;
262   id   edom;
263   id   old;
264   BOOL doForm;
265   NSTimeInterval st = 0.0;
266
267   if (profileComponents)
268     st = [[NSDateClass date] timeIntervalSince1970];
269
270 #if DEBUG
271   if ([_ctx isInForm]) {
272     NSLog(@"WARNING(%s): this element shouldn't be used in forms, it generates "
273           @"it's own one.", __PRETTY_FUNCTION__);
274   }
275 #endif
276   
277   cmp = [_ctx component];
278   
279 #if DEBUG_DOM
280   NSAssert(_ctx,      @"missing context ..");
281   NSAssert(_response, @"missing response ..");
282   NSAssert(cmp,       @"missing component ..");
283   [_response appendContentString:@"<!-- renderdom-begin -->"];
284 #endif
285   
286   if ((edom = [self domInContext:_ctx]) == nil) {
287 #if DEBUG_DOM
288     [cmp logWithFormat:@"no DOM to render .."];
289     [_response appendContentString:@"<!-- missing dom -->"];
290 #endif
291     return;
292   }
293   
294   old = [self pushToCtx:_ctx];
295   
296   if ((lrenderer = [self rendererForNode:edom inContext:_ctx]) == nil) {
297 #if DEBUG_DOM
298     [cmp logWithFormat:@"did not find renderer for node %@", edom];
299     [_response appendContentString:@"<!-- missing dom renderer -->"];
300 #endif
301     return;
302   }
303   
304   doForm = [self _requiresFormInContext:_ctx node:edom renderer:lrenderer];
305   
306   if (doForm) {
307     [_response appendContentString:@"<form method=\"post\" action=\""];
308     [_response appendContentString:[_ctx componentActionURL]];
309     [_response appendContentString:@"\">"];
310     [_ctx setInForm:YES];
311   }
312   
313 #if DEBUG_DOM
314   [cmp logWithFormat:@"render dom %@ using %@", edom, lrenderer];
315   NSAssert(lrenderer, @"lost renderer ..");
316 #endif
317   
318   [lrenderer appendNode:edom
319              toResponse:_response
320              inContext:_ctx];
321   
322   if (doForm) {
323     [_ctx setInForm:NO];
324     [_response appendContentString:@"</form>"];
325   }
326
327 #if DEBUG_DOM
328   NSAssert(_response, @"lost response ..");
329   [_response appendContentString:@"<!-- renderdom-end -->"];
330 #endif
331   
332   [self popFromCtx:_ctx old:old];
333   
334   if (profileComponents) {
335     NSTimeInterval diff;
336     int i;
337     diff = [[NSDateClass date] timeIntervalSince1970] - st;
338     for (i = [_ctx componentStackCount]; i >= 0; i--)
339       printf("  ");
340     printf("[%s %s]: %0.3fs (component=%s)\n",
341            "WORenderDOM", sel_get_name(_cmd), diff,
342            [[(WOComponent *)[_ctx component] name] cString]);
343   }
344 }
345
346 @end /* WORenderDOM */