]> err.no Git - sope/blob - Recycler/NGObjDOM/ODNodeRenderer+attributes.m
use %p for pointer formats
[sope] / Recycler / NGObjDOM / ODNodeRenderer+attributes.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/ODNodeRenderer+attributes.h>
24 #include <NGObjDOM/ODNodeRenderer.h>
25 #include <NGObjDOM/ODNamespaces.h>
26 #include <NGObjDOM/WOContext+Cursor.h>
27 #include "common.h"
28
29 @interface ODNodeRenderer(PrivateMethodes)
30 - (id)attributeNodeNamed:(NSString *)_attr ofNode:(id)_node inContext:(id)_ctx;
31 - (id)stringValueForAttributeNode:(id)_attrNode inContext:(id)_ctx;
32 @end
33
34 @interface NSObject(NGScriptEval)
35 - (id)evaluateScript:(NSString *)_script language:(NSString *)_lang;
36 @end
37
38 @implementation ODNodeRenderer(attributes)
39
40 static BOOL evalJSInHandler = NO;
41 static BOOL debugJS         = NO;
42 static BOOL logValues       = NO;
43
44 static void _categoryInitialize(void) {
45   NSUserDefaults *ud;
46   static BOOL didInit = NO;
47   if (didInit) return;
48   
49   ud = [NSUserDefaults standardUserDefaults];
50   evalJSInHandler = [ud boolForKey:@"ODEvalAttrValuesInExceptionHandler"];
51   debugJS         = [ud boolForKey:@"ODDebugJSAttrEval"];
52   logValues       = [ud boolForKey:@"ODLogAttrValues"];
53   
54   didInit = YES;
55 }
56
57 /* attributes */
58
59 - (BOOL)boolFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
60   id       attrNode;
61   NSString *value;
62   
63   attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
64   value    = [[self valueForAttributeNode:attrNode inContext:_ctx] stringValue];
65
66   if (logValues)
67     NSLog(@"%s: bool for attr %@ => '%@'", __PRETTY_FUNCTION__, _attr, value);
68   
69   if ([value isEqualToString:@"true"])
70     return YES;
71   if ([value isEqualToString:@"false"])
72     return NO;
73   
74   return [value boolValue];
75 }
76
77 - (int)intFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
78   id attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
79   
80   return [[self valueForAttributeNode:attrNode inContext:_ctx] intValue];
81 }
82
83 - (id)valueFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
84   id attrNode;
85   
86   attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
87   
88   return [self valueForAttributeNode:attrNode inContext:_ctx];
89 }
90
91 - (NSString *)stringFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
92   id attrNode;
93   
94   attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
95   
96   return [self stringValueForAttributeNode:attrNode inContext:_ctx];
97 }
98
99 - (void)setValue:(id)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
100   id attrNode = nil;
101   id<DOMNamedNodeMap> attrs;
102
103   NSAssert2((_attr != nil),
104             @"%s: Cannot set '%@' (The attributeName is nil!)",
105             __PRETTY_FUNCTION__, _value);
106
107   NSAssert3(((attrs = [_node attributes]) != nil),
108            @"%s: Cannot set '%@' for '%@' (There are no attributes!)",
109            __PRETTY_FUNCTION__, _value, _attr);
110   
111   attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_BIND];
112   
113   NSAssert4((attrNode != nil),
114             @"%s: Cannot set '%@' for '%@:%@' (There is not such attribute!)",
115             __PRETTY_FUNCTION__, _value, XMLNS_OD_BIND, _attr);
116
117   [[(id<WOPageGenerationContext>)_ctx cursor] 
118     takeValue:_value forKeyPath:[attrNode value]];
119 }
120
121 - (void)setBool:(BOOL)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
122   [self setValue:[NSNumber numberWithBool:_value]
123         for:_attr
124         node:_node
125         ctx:_ctx];
126 }
127
128 - (void)setInt:(int)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
129   [self setValue:[NSNumber numberWithInt:_value]
130         for:_attr
131         node:_node
132         ctx:_ctx];  
133 }
134
135 - (void)setString:(NSString *)_value
136   for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
137 {
138   [self setValue:[_value stringValue] for:_attr node:_node ctx:_ctx];
139 }
140
141 - (void)forceSetValue:(id)_value
142   for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
143 {
144   if ([self isSettable:_attr node:_node ctx:_ctx])
145     [self setValue:_value for:_attr node:_node ctx:_ctx];
146   else
147     [_node setAttribute:_attr namespaceURI:XMLNS_OD_CONST value:_value];
148 }
149
150 - (void)forceSetBool:(BOOL)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
151   [self forceSetValue:[NSNumber numberWithBool:_value]
152         for:_attr
153         node:_node
154         ctx:_ctx];
155 }
156
157 - (void)forceSetInt:(int)_value
158   for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
159 {
160   [self forceSetValue:[NSNumber numberWithInt:_value]
161         for:_attr
162         node:_node
163         ctx:_ctx];  
164 }
165
166 - (void)forceSetString:(NSString *)_value
167   for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
168 {
169   [self forceSetValue:[_value stringValue] for:_attr node:_node ctx:_ctx];
170 }
171
172
173 - (BOOL)hasAttribute:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
174   return ([self attributeNodeNamed:_attr ofNode:_node inContext:_ctx] != nil)
175     ? YES
176     : NO;
177 }
178
179 - (BOOL)isSettable:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
180   id attrNode = nil;
181   id<DOMNamedNodeMap> attrs;
182   
183   if ((attrs = [_node attributes]) == nil)
184     return NO;
185   
186   if (!(attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_BIND]))
187     return NO;
188
189   return ([[attrNode value] length] > 0) ? YES : NO;
190 }
191
192 - (NSString *)stringForInt:(int)_value {
193   static NSString *strs[10] = {
194     @"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9" };
195   
196   if (_value < 10 && _value >= 0)
197     return strs[_value];
198   
199   return [NSString stringWithFormat:@"%i", _value];
200 }
201
202 /* evaluate associations (looks for 'special' namespaces) */
203
204 - (NSException *)handleEvalException:(NSException *)_exception
205   onNode:(id)_attrNode inContext:(id)_ctx 
206 {
207   [self logWithFormat:@"Eval Node %@ catched: %@", _attrNode, _exception];
208   return nil;
209 }
210
211 - (id)valueForAttributeNode:(id)_attrNode inContext:(id)_ctx {
212   NSString *nsuri;
213   NSString *value;
214   
215   _categoryInitialize();
216   
217   if (_attrNode == nil) {
218     return nil;
219   }
220   
221   nsuri = [_attrNode namespaceURI];
222   value = [_attrNode value];
223   
224   if (logValues) {
225     [self logWithFormat:
226             @"%s:\n  value for attr %@\n  (ns=%@, value='%@', cursor=%@) ...",
227             __PRETTY_FUNCTION__, _attrNode, nsuri, value, 
228             [(id<WOPageGenerationContext>)_ctx cursor]];
229   }
230   
231   if ([nsuri isEqualToString:XMLNS_OD_CONST]) {
232     // do nothing ...
233     if (logValues) [self logWithFormat:@"    constant value, pass through"];
234   }
235   else if ([nsuri isEqualToString:XMLNS_OD_BIND]) {
236     if (logValues) {
237       [self logWithFormat:@"    cursor: %@\n    valueForKeyPath:'%@'", 
238               [(id<WOPageGenerationContext>)_ctx cursor], value];
239     }
240     value = [[(id<WOPageGenerationContext>)_ctx cursor] valueForKeyPath:value];
241   }
242   else if ([nsuri isEqualToString:XMLNS_OD_ACTION]) {
243     // TODO: is this ever used anywhere ? (hm, maybe in forms)
244     // Note: the node-value gets used in the dispatch phase !
245     if (logValues) [self logWithFormat:@"    componentAction: '%@'", value];
246     value = [_ctx componentActionURL];
247   }
248   else if ([nsuri isEqualToString:XMLNS_OD_EVALJS]) {
249     id cursor;
250     
251     if (logValues) [self logWithFormat:@"    JavaScript: '%@'", value];
252     
253     cursor = [(id<WOPageGenerationContext>)_ctx cursor];
254     if ([cursor respondsToSelector:@selector(evaluateScript:language:)]) {
255       if (debugJS)
256         [self logWithFormat:@"\n  cursor %@\n  eval: '%@'", cursor, value];
257       
258       if (!evalJSInHandler) {
259         value = [cursor evaluateScript:value language:@"javascript"];
260       }
261       else {
262         NS_DURING
263           value = [cursor evaluateScript:value language:@"javascript"];
264         NS_HANDLER
265           [[self handleEvalException:localException
266                  onNode:_attrNode inContext:_ctx] raise];
267         NS_ENDHANDLER;
268       }
269       
270       if (debugJS) [self logWithFormat:@"  got: %@", value];
271     }
272     else {
273       [self logWithFormat:
274               @"%s:\n  object %@ cannot evaluate JavaScript\n'%@' !!",
275               __PRETTY_FUNCTION__, self, value];
276     }
277   }
278   
279   if (logValues) {
280     [self logWithFormat:@"  return value: %@ (%@,0x%p)\n", 
281             value ? value: @"<nil>", NSStringFromClass([value class]), value];
282   }
283   return value;
284 }
285
286 - (id)invokeValueForAttributeNode:(id)_attrNode inContext:(id)_ctx {
287   NSString *nsuri;
288   id result;
289
290   result = nil;
291   
292   if ((nsuri = [_attrNode namespaceURI])) {
293     if ([nsuri isEqualToString:XMLNS_OD_ACTION])
294       result = [[_ctx component] valueForKeyPath:[_attrNode value]];
295   }
296   if (result == nil)
297     result = [self valueForAttributeNode:_attrNode inContext:_ctx];
298   
299   if (![result conformsToProtocol:@protocol(WOActionResults)])
300     return nil;
301   
302   return result;
303 }
304
305 @end /* ODNodeRenderer(attributes) */
306
307 @implementation ODNodeRenderer(PrivateMethodes)
308
309 - (id)attributeNodeNamed:(NSString *)_attr ofNode:(id)_node inContext:(id)_ctx{
310   id attrNode;
311   id<DOMNamedNodeMap> attrs;
312   
313   if ((attrs = [_node attributes]) == nil)
314     return nil;
315   
316   attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_CONST];
317   if (attrNode == nil)
318     attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_BIND];
319   if (attrNode == nil)
320     attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_XUL];
321   if (attrNode == nil)
322     attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_XHTML];
323   if (attrNode == nil)
324     attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_HTML40];
325   if (attrNode == nil)
326     attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_EVALJS];
327
328   if (attrNode == nil)
329     attrNode = [_node attributeNode:_attr namespaceURI:@"*"];
330   
331 #if DEBUG && 0
332   if (attrNode == nil) {
333     NSLog(@"%s: found no attribute named %@ in node %@", __PRETTY_FUNCTION__,
334           _attr, _node);
335   }
336 #endif
337   return attrNode;
338 }
339
340 - (id)stringValueForAttributeNode:(id)_attrNode inContext:(id)_ctx {
341   if ([[_attrNode namespaceURI] isEqualToString:XMLNS_XUL]) {
342     if ([[(id<DOMAttr>)_attrNode name] isEqualToString:@"src"]) {
343       /* a URL */
344       NSURL *url;
345       id rm;
346       
347       if ((url = [NSURL URLWithString:[_attrNode value]])) {
348         /* valid, regular URL */
349         return [[_attrNode value] stringValue];
350       }
351       
352       /* consider it a resource name */
353       rm = [[_ctx component] resourceManager];
354       return [rm urlForResourceNamed:[_attrNode value]
355                  inFramework:nil
356                  languages:[[_ctx session] languages]
357                  request:[(WOContext *)_ctx request]];
358     }
359
360     if ([(NSString *)[(id<DOMAttr>)_attrNode name] hasPrefix:@"on"])
361       return [[_ctx elementID] stringValue];
362   }
363   return [[self valueForAttributeNode:_attrNode inContext:_ctx] stringValue];
364 }
365
366 @end /* ODNodeRenderer(PrivateMethodes) */