2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
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.
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
23 #include <NGObjDOM/ODNodeRenderer.h>
24 #include <EOControl/EOKeyValueCoding.h>
31 <var:form const:src="/blah.sfm">
32 <var:param const:name="color" const:value="green"/>
33 <var:param const:name="document" value="document"/>
44 NOTE: currently the context is stacked to the parent during the
48 @interface ODR_bind_form : ODNodeRenderer
54 #include "used_privates.h"
55 #include <NGObjDOM/ODNodeRendererFactory.h>
56 #include <NGObjDOM/ODNamespaces.h>
58 #include <NGObjWeb/NGObjWeb.h>
60 @interface _ODRBindFormTemplateWrapper : WODynamicElement
63 @interface WOComponent(BindFormSupport)
64 - (void)_addChildForm:(WOComponent *)_form withId:(NSString *)_fid;
65 - (void)setSubComponents:(NSDictionary *)_sc;
66 - (NSDictionary *)_subComponents;
67 - (WOComponent *)childComponentWithName:(NSString *)_name;
70 @implementation WOComponent(ChildForms)
72 - (void)_addChildForm:(WOComponent *)_form withId:(NSString *)_fid {
73 NSMutableDictionary *msc;
76 if (_form == nil) return;
77 if ([_fid length] == 0) return;
79 sc = [self _subComponents];
82 : [[NSMutableDictionary alloc] initWithCapacity:4];
84 [msc setObject:_form forKey:_fid];
86 [self setSubComponents:msc];
87 RELEASE(msc); msc = nil;
90 @end /* WOComponent(ChildForms) */
92 @implementation ODR_bind_form
94 - (WOComponent *)_childComponentForNode:(id)_node
95 inContext:(WOContext *)_ctx
97 WOComponent *form, *parent;
104 parent = [_ctx component];
106 /* try to lookup in cache */
108 fid = [self stringFor:@"id" node:_node ctx:_ctx];
110 if ([fid length] == 0)
111 fid = [self uniqueIDForNode:_node inContext:_ctx];
113 if ([fid length] > 0) {
114 fid = [NSString stringWithFormat:@"ODR_bind_form:%@", fid];
116 NSLog(@"FID: %@", fid);
119 if ((form = [parent childComponentWithName:fid]))
123 /* try to instantiate form */
125 if ((src = [self stringFor:@"src" node:_node ctx:_ctx])) {
126 //NSLog(@"%s: embed form '%@'", __PRETTY_FUNCTION__, src);
128 PROFILE_CHECKPOINT("begin loading ..");
130 // NSLog(@"loading '%@' ...", src);
131 form = [parent pageWithName:src];
133 PROFILE_CHECKPOINT("and not a page form ..");
136 [parent logWithFormat:@"(%@): found no subform at src '%@'",
137 NSStringFromClass([parent class]), src];
141 /* insert form in cache ... */
142 if (form) [[_ctx component] _addChildForm:form withId:fid];
149 - (WOElement *)_childContentForNode:(id)_node inContext:(WOContext *)_ctx {
153 - (void)_syncComponent:(WOComponent *)_form
154 parent:(WOComponent *)_parent
157 inContext:(WOContext *)_ctx
159 /* Watch out for correct context when calling this method ! */
160 static DOMQueryPathExpression *qpexpr = nil;
161 NSEnumerator *childNodes;
170 qpexpr = [[DOMQueryPathExpression queryPathWithString:@"-param"] retain];
173 ? [(NSArray *)[_node childNodes] objectEnumerator]
174 : [(NSArray *)[_node childNodes] reverseObjectEnumerator];
176 while ((childNode = [childNodes nextObject])) {
181 if ([childNode nodeType] != DOM_ELEMENT_NODE)
183 if (![[childNode tagName] isEqualToString:@"param"])
186 pname = [self stringFor:@"name" node:childNode ctx:_ctx];
187 ptype = [self stringFor:@"type" node:childNode ctx:_ctx];
192 if ([ptype isEqualToString:@"in"])
195 attrNode = [[childNode attributes]
197 namespaceURI:XMLNS_OD_BIND];
198 if (attrNode == nil) {
200 NSLog(@"%s: no up sync possible, missing proper value attribute ..",
201 __PRETTY_FUNCTION__);
206 pvalue = [_form valueForKey:pname];
210 logWithFormat:@"sync up value %@ to %@", pvalue, [attrNode value]];
213 [_parent takeValue:pvalue forKeyPath:[attrNode value]];
216 if ([ptype isEqualToString:@"out"])
219 pvalue = [self valueFor:@"value" node:childNode ctx:_ctx];
223 @"sync down value '%@' to '%@'", pvalue, pname];
226 [_form takeValue:pvalue forKey:pname];
233 - (void)takeValuesForNode:(id)_node
234 fromRequest:(WORequest *)_request
235 inContext:(WOContext *)_ctx
237 WOComponent *childComponent;
238 WOComponent *parentComponent;
240 childComponent = [self _childComponentForNode:_node inContext:_ctx];
241 if (childComponent == nil)
244 parentComponent = [_ctx component];
246 [self _syncComponent:childComponent
247 parent:parentComponent
252 [_ctx enterComponent:childComponent
253 content:[self _childContentForNode:_node inContext:_ctx]];
255 [childComponent takeValuesFromRequest:_request inContext:_ctx];
257 [_ctx leaveComponent:childComponent];
259 [self _syncComponent:childComponent
260 parent:parentComponent
266 - (id)invokeActionForNode:(id)_node
267 fromRequest:(WORequest *)_request
268 inContext:(WOContext *)_ctx
270 WOComponent *childComponent;
271 WOComponent *parentComponent;
276 childComponent = [self _childComponentForNode:_node inContext:_ctx];
277 if (childComponent == nil) {
279 [[_ctx component] debugWithFormat:@"missing child component .."];
284 parentComponent = [_ctx component];
286 [self _syncComponent:childComponent
287 parent:parentComponent
292 [_ctx enterComponent:childComponent
293 content:[self _childContentForNode:_node inContext:_ctx]];
296 [[_ctx component] debugWithFormat:@" %s\nsid=%@\neid=%@",
298 [_ctx senderID], [_ctx elementID]];
301 result = [childComponent invokeActionForRequest:_request inContext:_ctx];
303 [_ctx leaveComponent:childComponent];
305 [self _syncComponent:childComponent
306 parent:parentComponent
316 - (void)appendNode:(id)_node
317 toResponse:(WOResponse *)_response
318 inContext:(WOContext *)_ctx
320 WOComponent *childComponent;
321 WOComponent *parentComponent;
325 childComponent = [self _childComponentForNode:_node inContext:_ctx];
326 if (childComponent == nil)
329 parentComponent = [_ctx component];
331 PROFILE_CHECKPOINT("sync down ..");
333 [self _syncComponent:childComponent
334 parent:parentComponent
339 PROFILE_CHECKPOINT("enter stack ..");
341 [_ctx enterComponent:childComponent
342 content:[self _childContentForNode:_node inContext:_ctx]];
344 PROFILE_CHECKPOINT("append child ..");
346 [childComponent appendToResponse:_response inContext:_ctx];
348 PROFILE_CHECKPOINT("leave stack ..");
350 [_ctx leaveComponent:childComponent];
352 PROFILE_CHECKPOINT("sync up ..");
354 [self _syncComponent:childComponent
355 parent:parentComponent
363 @end /* ODR_bind_embed */
365 @implementation _ODRBindFormTemplateWrapper
367 - (id)_nodeInContext:(WOContext *)_ctx {
371 - (ODNodeRenderer *)rendererForNode:(id)_domNode inContext:(WOContext *)_ctx {
372 id<ODNodeRendererFactory> factory;
373 ODNodeRenderer *renderer = nil;
375 if ((factory = [_ctx objectForKey:@"domRenderFactory"]))
376 renderer = [factory rendererForNode:_domNode inContext:_ctx];
381 - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
382 ODNodeRenderer *lrenderer = nil;
385 if ((dom = [self _nodeInContext:_ctx]) == nil)
388 [lrenderer takeValuesForNode:dom
393 - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
394 ODNodeRenderer *lrenderer = nil;
397 if ((dom = [self _nodeInContext:_ctx]) == nil)
400 return [lrenderer invokeActionForNode:dom
405 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
406 ODNodeRenderer *lrenderer;
409 if ((dom = [self _nodeInContext:_ctx]) == nil)
412 if ((lrenderer = [self rendererForNode:dom inContext:_ctx]) == nil) {
414 [cmp logWithFormat:@"did not find renderer for node %@", dom];
415 [_response appendContentString:@"<!-- missing dom renderer -->"];
421 NSAssert(lrenderer, @"lost renderer ..");
424 [lrenderer appendNode:dom
429 NSAssert(_response, @"lost response ..");
430 [_response appendContentString:@"<!-- renderdom-end -->"];
434 @end /* _ODRBindFormTemplateWrapper */