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+attributes.h>
24 #include <NGObjDOM/ODNodeRenderer.h>
25 #include <NGObjDOM/ODNamespaces.h>
26 #include <NGObjDOM/WOContext+Cursor.h>
29 @interface ODNodeRenderer(PrivateMethodes)
30 - (id)attributeNodeNamed:(NSString *)_attr ofNode:(id)_node inContext:(id)_ctx;
31 - (id)stringValueForAttributeNode:(id)_attrNode inContext:(id)_ctx;
34 @interface NSObject(NGScriptEval)
35 - (id)evaluateScript:(NSString *)_script language:(NSString *)_lang;
38 @implementation ODNodeRenderer(attributes)
40 static BOOL evalJSInHandler = NO;
41 static BOOL debugJS = NO;
42 static BOOL logValues = NO;
44 static void _categoryInitialize(void) {
46 static BOOL didInit = NO;
49 ud = [NSUserDefaults standardUserDefaults];
50 evalJSInHandler = [ud boolForKey:@"ODEvalAttrValuesInExceptionHandler"];
51 debugJS = [ud boolForKey:@"ODDebugJSAttrEval"];
52 logValues = [ud boolForKey:@"ODLogAttrValues"];
59 - (BOOL)boolFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
63 attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
64 value = [[self valueForAttributeNode:attrNode inContext:_ctx] stringValue];
67 NSLog(@"%s: bool for attr %@ => '%@'", __PRETTY_FUNCTION__, _attr, value);
69 if ([value isEqualToString:@"true"])
71 if ([value isEqualToString:@"false"])
74 return [value boolValue];
77 - (int)intFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
78 id attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
80 return [[self valueForAttributeNode:attrNode inContext:_ctx] intValue];
83 - (id)valueFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
86 attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
88 return [self valueForAttributeNode:attrNode inContext:_ctx];
91 - (NSString *)stringFor:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
94 attrNode = [self attributeNodeNamed:_attr ofNode:_node inContext:_ctx];
96 return [self stringValueForAttributeNode:attrNode inContext:_ctx];
99 - (void)setValue:(id)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
101 id<DOMNamedNodeMap> attrs;
103 NSAssert2((_attr != nil),
104 @"%s: Cannot set '%@' (The attributeName is nil!)",
105 __PRETTY_FUNCTION__, _value);
107 NSAssert3(((attrs = [_node attributes]) != nil),
108 @"%s: Cannot set '%@' for '%@' (There are no attributes!)",
109 __PRETTY_FUNCTION__, _value, _attr);
111 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_BIND];
113 NSAssert4((attrNode != nil),
114 @"%s: Cannot set '%@' for '%@:%@' (There is not such attribute!)",
115 __PRETTY_FUNCTION__, _value, XMLNS_OD_BIND, _attr);
117 [[(id<WOPageGenerationContext>)_ctx cursor]
118 takeValue:_value forKeyPath:[attrNode value]];
121 - (void)setBool:(BOOL)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
122 [self setValue:[NSNumber numberWithBool:_value]
128 - (void)setInt:(int)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
129 [self setValue:[NSNumber numberWithInt:_value]
135 - (void)setString:(NSString *)_value
136 for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
138 [self setValue:[_value stringValue] for:_attr node:_node ctx:_ctx];
141 - (void)forceSetValue:(id)_value
142 for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
144 if ([self isSettable:_attr node:_node ctx:_ctx])
145 [self setValue:_value for:_attr node:_node ctx:_ctx];
147 [_node setAttribute:_attr namespaceURI:XMLNS_OD_CONST value:_value];
150 - (void)forceSetBool:(BOOL)_value for:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
151 [self forceSetValue:[NSNumber numberWithBool:_value]
157 - (void)forceSetInt:(int)_value
158 for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
160 [self forceSetValue:[NSNumber numberWithInt:_value]
166 - (void)forceSetString:(NSString *)_value
167 for:(NSString *)_attr node:(id)_node ctx:(id)_ctx
169 [self forceSetValue:[_value stringValue] for:_attr node:_node ctx:_ctx];
173 - (BOOL)hasAttribute:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
174 return ([self attributeNodeNamed:_attr ofNode:_node inContext:_ctx] != nil)
179 - (BOOL)isSettable:(NSString *)_attr node:(id)_node ctx:(id)_ctx {
181 id<DOMNamedNodeMap> attrs;
183 if ((attrs = [_node attributes]) == nil)
186 if (!(attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_BIND]))
189 return ([[attrNode value] length] > 0) ? YES : NO;
192 - (NSString *)stringForInt:(int)_value {
193 static NSString *strs[10] = {
194 @"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9" };
196 if (_value < 10 && _value >= 0)
199 return [NSString stringWithFormat:@"%i", _value];
202 /* evaluate associations (looks for 'special' namespaces) */
204 - (NSException *)handleEvalException:(NSException *)_exception
205 onNode:(id)_attrNode inContext:(id)_ctx
207 [self logWithFormat:@"Eval Node %@ catched: %@", _attrNode, _exception];
211 - (id)valueForAttributeNode:(id)_attrNode inContext:(id)_ctx {
215 _categoryInitialize();
217 if (_attrNode == nil) {
221 nsuri = [_attrNode namespaceURI];
222 value = [_attrNode value];
226 @"%s:\n value for attr %@\n (ns=%@, value='%@', cursor=%@) ...",
227 __PRETTY_FUNCTION__, _attrNode, nsuri, value,
228 [(id<WOPageGenerationContext>)_ctx cursor]];
231 if ([nsuri isEqualToString:XMLNS_OD_CONST]) {
233 if (logValues) [self logWithFormat:@" constant value, pass through"];
235 else if ([nsuri isEqualToString:XMLNS_OD_BIND]) {
237 [self logWithFormat:@" cursor: %@\n valueForKeyPath:'%@'",
238 [(id<WOPageGenerationContext>)_ctx cursor], value];
240 value = [[(id<WOPageGenerationContext>)_ctx cursor] valueForKeyPath:value];
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];
248 else if ([nsuri isEqualToString:XMLNS_OD_EVALJS]) {
251 if (logValues) [self logWithFormat:@" JavaScript: '%@'", value];
253 cursor = [(id<WOPageGenerationContext>)_ctx cursor];
254 if ([cursor respondsToSelector:@selector(evaluateScript:language:)]) {
256 [self logWithFormat:@"\n cursor %@\n eval: '%@'", cursor, value];
258 if (!evalJSInHandler) {
259 value = [cursor evaluateScript:value language:@"javascript"];
263 value = [cursor evaluateScript:value language:@"javascript"];
265 [[self handleEvalException:localException
266 onNode:_attrNode inContext:_ctx] raise];
270 if (debugJS) [self logWithFormat:@" got: %@", value];
274 @"%s:\n object %@ cannot evaluate JavaScript\n'%@' !!",
275 __PRETTY_FUNCTION__, self, value];
280 [self logWithFormat:@" return value: %@ (%@,0x%08X)\n",
281 value ? value: @"<nil>", NSStringFromClass([value class]), value];
286 - (id)invokeValueForAttributeNode:(id)_attrNode inContext:(id)_ctx {
292 if ((nsuri = [_attrNode namespaceURI])) {
293 if ([nsuri isEqualToString:XMLNS_OD_ACTION])
294 result = [[_ctx component] valueForKeyPath:[_attrNode value]];
297 result = [self valueForAttributeNode:_attrNode inContext:_ctx];
299 if (![result conformsToProtocol:@protocol(WOActionResults)])
305 @end /* ODNodeRenderer(attributes) */
307 @implementation ODNodeRenderer(PrivateMethodes)
309 - (id)attributeNodeNamed:(NSString *)_attr ofNode:(id)_node inContext:(id)_ctx{
311 id<DOMNamedNodeMap> attrs;
313 if ((attrs = [_node attributes]) == nil)
316 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_CONST];
318 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_BIND];
320 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_XUL];
322 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_XHTML];
324 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_HTML40];
326 attrNode = [attrs namedItem:_attr namespaceURI:XMLNS_OD_EVALJS];
329 attrNode = [_node attributeNode:_attr namespaceURI:@"*"];
332 if (attrNode == nil) {
333 NSLog(@"%s: found no attribute named %@ in node %@", __PRETTY_FUNCTION__,
340 - (id)stringValueForAttributeNode:(id)_attrNode inContext:(id)_ctx {
341 if ([[_attrNode namespaceURI] isEqualToString:XMLNS_XUL]) {
342 if ([[(id<DOMAttr>)_attrNode name] isEqualToString:@"src"]) {
347 if ((url = [NSURL URLWithString:[_attrNode value]])) {
348 /* valid, regular URL */
349 return [[_attrNode value] stringValue];
352 /* consider it a resource name */
353 rm = [[_ctx component] resourceManager];
354 return [rm urlForResourceNamed:[_attrNode value]
356 languages:[[_ctx session] languages]
357 request:[(WOContext *)_ctx request]];
360 if ([(NSString *)[(id<DOMAttr>)_attrNode name] hasPrefix:@"on"])
361 return [[_ctx elementID] stringValue];
363 return [[self valueForAttributeNode:_attrNode inContext:_ctx] stringValue];
366 @end /* ODNodeRenderer(PrivateMethodes) */