]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOxHTMLElemBuilder.m
improved query string handling
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOxHTMLElemBuilder.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 #import <NGObjWeb/WOxElemBuilder.h>
23
24 /*
25   This builder builds all standard elements which are defined in the XHTML
26   or HTML 4 namespace.
27
28   Supported tags:
29     - all other tags are represented using either WOGenericElement or
30       WOGenericContainer, so this builder is "final destination" for
31       all HTML related tags.
32   
33     <input> - the "type" attribute of the input must be static and further
34               specifies the generated element
35       type="submit"   maps to WOSubmitButton
36       type="reset"    maps to WOResetButton
37       type="image"    maps to WOImageButton
38       type="radio"    maps to WORadioButton
39       type="checkbox" maps to WOCheckBox
40       type="file"     maps to WOFileUpload
41       type="hidden"   maps to WOHiddenField
42       type="password" maps to WOPasswordField
43       TODO: button!
44       all other       map  to WOTextField
45     <a>..</a>         maps to WOHyperlink
46     <img .../>        maps to WOImage
47     <form .../>       maps to WOForm
48     <textarea .../>   maps to WOText
49     <embed .../>      maps to WOEmbeddedObject
50     <frame .../>      maps to WOFrame
51     <iframe .../>     maps to WOIFrame
52     <body .../>       maps to WOBody
53     <entity .../>     maps to WOEntity
54     <container .../>  removes the tag and embeds the content
55 */
56
57 @interface WOxHTMLElemBuilder : WOxTagClassElemBuilder
58 {
59 }
60
61 @end
62
63 #include "WOCompoundElement.h"
64 #include "decommon.h"
65 #include <SaxObjC/XMLNamespaces.h>
66
67 @implementation WOxHTMLElemBuilder
68
69 static Class WOGenericContainerClass = Nil;
70 static Class WOGenericElementClass   = Nil;
71
72 + (void)initialize {
73   WOGenericContainerClass = NSClassFromString(@"WOGenericContainer");
74   WOGenericElementClass   = NSClassFromString(@"WOGenericElement");
75 }
76
77 - (Class)classForInputElement:(id<DOMElement>)_element {
78   NSString *type;
79   unsigned tl;
80   unichar c1;
81   
82   type = [_element attribute:@"type" namespaceURI:XMLNS_XHTML];
83   tl = [type length];
84
85   if (tl == 0)
86     return NSClassFromString(@"WOTextField");
87   else if (tl > 0)
88     c1 = [type characterAtIndex:0];
89   
90   switch (tl) {
91     case 0:
92
93     case 4:
94       if (c1 == 't') {
95         if ([type isEqualToString:@"text"])
96           return NSClassFromString(@"WOTextField");
97       }
98       else if (c1 == 'f') {
99         if ([type isEqualToString:@"file"])
100           return NSClassFromString(@"WOFileUpload");
101       }
102       break;
103       
104     case 5:
105       if (c1 == 'i' && [type isEqualToString:@"image"])
106         return NSClassFromString(@"WOImageButton");
107       else if (c1 == 'r') {
108         if ([type isEqualToString:@"radio"])
109           return NSClassFromString(@"WORadioButton");
110         if ([type isEqualToString:@"reset"])
111           return NSClassFromString(@"WOResetButton");
112       }
113       break;
114       
115     case 6:
116       if (c1 == 's' && [type isEqualToString:@"submit"])
117         return NSClassFromString(@"WOSubmitButton");
118       else if (c1 == 'h' && [type isEqualToString:@"hidden"])
119         return NSClassFromString(@"WOHiddenField");
120       else if (c1 == 'b' && [type isEqualToString:@"button"])
121         return NSClassFromString(@"WOGenericElement");
122       break;
123
124     case 8:
125       if (c1 == 'c' && [type isEqualToString:@"checkbox"])
126         return NSClassFromString(@"WOCheckBox");
127       else if (c1 == 'p' && [type isEqualToString:@"password"])
128         return NSClassFromString(@"WOPasswordField");
129       
130     default:
131       break;
132   }
133   
134   [self warnWithFormat:@"unknown input type '%@' !", type];
135   return NSClassFromString(@"WOTextField");
136 }
137
138 - (Class)classForElement:(id<DOMElement>)_element {
139   /* Note: namespace is checked in build-element */
140   NSString *tag;
141   unsigned tl;
142   unichar  c0;
143
144   tag = [_element tagName];
145   
146   if ((tl = [tag length]) == 0)
147     return Nil;
148   c0 = [tag characterAtIndex:0];
149   
150   switch (tl) {
151     case 1:
152       if (c0 == 'a') {
153         // TODO: improve this section
154         if ([_element hasAttribute:@"name" namespaceURI:@"*"])
155           return NSClassFromString(@"WOGenericContainer");
156         
157         return NSClassFromString(@"WOHyperlink");
158       }
159       break;
160
161     case 3:
162       if (c0 == 'i' && [tag isEqualToString:@"img"])
163         return NSClassFromString(@"WOImage");
164       break;
165
166     case 4:
167       if (c0 == 'b' && [tag isEqualToString:@"body"])
168         return NSClassFromString(@"WOBody");
169 #if WRAP_HTML_ROOT_TAG
170       if (c0 == 'h' && [tag isEqualToString:@"html"])
171         return NSClassFromString(@"WOHtml");
172 #endif
173       if (c0 == 'f' && [tag isEqualToString:@"form"])
174         return NSClassFromString(@"WOForm");
175
176       if (c0 == 'm' && [tag isEqualToString:@"meta"]) {
177         NSString *val;
178         
179         val = [_element attribute:@"http-equiv" namespaceURI:XMLNS_XHTML];
180         if (val) {
181           val = [[val stringValue] lowercaseString];
182           if ([val hasPrefix:@"refresh"])
183             return NSClassFromString(@"WOMetaRefresh");
184         }
185       }
186       break;
187       
188     case 5:
189       if (c0 == 'i' && [tag isEqualToString:@"input"])
190         return [self classForInputElement:_element];
191       if (c0 == 'f' && [tag isEqualToString:@"frame"])
192         return NSClassFromString(@"WOFrame");
193       if (c0 == 'e' && [tag isEqualToString:@"embed"])
194         return NSClassFromString(@"WOEmbeddedObject");
195       break;
196
197     case 6:
198       if (c0 == 'i' && [tag isEqualToString:@"iframe"])
199         return NSClassFromString(@"WOIFrame");
200       if (c0 == 'e' && [tag isEqualToString:@"entity"])
201         return NSClassFromString(@"WOEntity");
202       break;
203
204     case 8:
205       if (c0 == 't' && [tag isEqualToString:@"textarea"])
206         return NSClassFromString(@"WOText");
207       break;
208   }
209   
210   return [_element hasChildNodes] 
211     ? WOGenericContainerClass
212     : WOGenericElementClass;
213 }
214
215 - (WOElement *)buildContainer:(id<DOMElement>)_element templateBuilder:(id)_b {
216   /*
217     this is a 'noop' tag, which only generates its children, useful
218     as a root tag for templates
219   */
220   NSArray *children;
221   unsigned count;
222   
223   children = [_element hasChildNodes]
224     ? [_b buildNodes:[_element childNodes] templateBuilder:_b]
225     : nil;
226
227   if ((count = [children count]) == 0)
228     return nil;
229   
230   if (count == 1)
231     return [[children objectAtIndex:0] retain];
232   
233   return [[WOCompoundElement allocForCount:count 
234                              zone:NULL] initWithContentElements:children];
235 }
236
237 - (WOElement *)buildElement:(id<DOMElement>)_element templateBuilder:(id)_b {
238   NSString *nsuri;
239
240   /* only build HTML namespace tags */
241   
242   if ((nsuri = [_element namespaceURI]) == nil)
243     return [self buildNextElement:_element templateBuilder:_b];
244   
245   if (![nsuri isEqualToString:XMLNS_XHTML]) {
246     /* check HTML 4 namespace */
247     if (![nsuri isEqualToString:XMLNS_HTML40])
248       return [self buildNextElement:_element templateBuilder:_b];
249   }
250   
251   /* check for container tag (has not class ...) */
252
253   if ([[_element tagName] isEqualToString:@"container"])
254     return [self buildContainer:_element templateBuilder:_b];
255   
256   /* call class based builder in superclass */
257   
258   return [super buildElement:_element templateBuilder:_b];
259 }
260
261 @end /* WOxHTMLElemBuilder */