2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.shale.clay.parser.builder;
22
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.TreeMap;
28
29 import org.apache.shale.clay.config.beans.ActionListenerBean;
30 import org.apache.shale.clay.config.beans.AttributeBean;
31 import org.apache.shale.clay.config.beans.ComponentBean;
32 import org.apache.shale.clay.config.beans.ConverterBean;
33 import org.apache.shale.clay.config.beans.ElementBean;
34 import org.apache.shale.clay.config.beans.SymbolBean;
35 import org.apache.shale.clay.config.beans.ValidatorBean;
36 import org.apache.shale.clay.config.beans.ValueChangeListenerBean;
37 import org.apache.shale.clay.parser.Node;
38 import org.apache.shale.util.Tags;
39
40 /***
41 * <p>A generic builder that maps the markup node name to the jsfid. The extends attribute
42 * can be used to override the default mapping to provide meta-data inheritance. The builder
43 * handles child nodes common to JSF and shale components.</p>
44 *
45 */
46 public class JsfDefaultBuilder extends ElementBuilder {
47
48 /***
49 * <p>Utility class that helps evaluate binding expressions.</p>
50 */
51 private Tags tagsUtil = new Tags();
52
53 /***
54 * <p>Contains the namespace prefix that should be used to locate
55 * clay configurations. This allows the page to use any prefix
56 * but still find the config element.</p>
57 */
58 private String prefix = null;
59
60 /***
61 * <p>Returns the namespace prefix that will be added to the
62 * node name when resolving the clay config.</p>
63 *
64 * @return URI prefix
65 */
66 public String getPrefix() {
67 return prefix;
68 }
69
70 /***
71 * <p>Sets the namespace preix that will override the template
72 * nodeds qname.</p>
73 *
74 * @param prefix URI prefix
75 */
76 public void setPrefix(String prefix) {
77 this.prefix = prefix;
78 }
79
80
81 /***
82 * <p>Factory method that creates a {@link ElementBean} from a {@link Node}.</p>
83 *
84 * @param node markup
85 * @return new config bean from the node
86 */
87 public ElementBean createElement(Node node) {
88 ElementBean target = new ElementBean();
89 target.setJsfid(getJsfid(node));
90 target.setRenderId(getRenderId());
91
92 return target;
93 }
94
95 /***
96 * <p>Holds a cross reference of commonsValidator type to
97 * a clay component config definition.</p>
98 */
99 private Map validatorsByType = null;
100 {
101 validatorsByType = new TreeMap();
102 validatorsByType.put("required", "s:commonsValidatorRequired");
103 validatorsByType.put("maxlength", "s:commonsValidatorMaxlength");
104 validatorsByType.put("minlength", "s:commonsValidatorMinlength");
105 validatorsByType.put("mask", "s:commonsValidatorMask");
106 validatorsByType.put("byte", "s:commonsValidatorByte");
107 validatorsByType.put("short", "s:commonsValidatorShort");
108 validatorsByType.put("integer", "s:commonsValidatorInteger");
109 validatorsByType.put("long", "s:commonsValidatorLong");
110 validatorsByType.put("float", "s:commonsValidatorFloat");
111 validatorsByType.put("double", "s:commonsValidatorDouble");
112 validatorsByType.put("date", "s:commonsValidatorDate");
113 validatorsByType.put("intRange", "s:commonsValidatorIntRange");
114 validatorsByType.put("floatRange", "s:commonsValidatorFloatRange");
115 validatorsByType.put("doubleRange", "s:commonsValidatorDoubleRange");
116 validatorsByType.put("creditCard", "s:commonsValidatorCreditCard");
117 validatorsByType.put("email", "s:commonsValidatorEmail");
118 validatorsByType.put("url", "s:commonsValidatorUrl");
119 }
120
121 /***
122 * @inheritDoc
123 * @param node markup
124 * @param target child config bean
125 */
126 protected void addConverter(Node node, ElementBean target) {
127 ConverterBean targetConverter = new ConverterBean();
128
129
130 Builder tmpBuilder = getBuilder(node);
131 ElementBean tmp = tmpBuilder.createElement(node);
132
133 String jsfid = tmp.getJsfid();
134 targetConverter.setJsfid(jsfid);
135
136 String converterId = (String) node.getAttributes().get("converterId");
137 if (converterId != null) {
138 targetConverter.setComponentType(tagsUtil.evalString(converterId));
139 }
140
141
142 if (node.getAttributes().containsKey("extends") || !jsfid.equals("converter")) {
143 realizeComponent(node, targetConverter);
144 }
145
146
147 target.addConverter(targetConverter);
148
149 }
150
151 /***
152 * <p>Looks for <s:validatorVar/> nodes within a <s:commonsValidator> node and
153 * converting them to {@link org.apache.shale.clay.config.beans.AttributeBean}'s
154 * on the <code>target</code> {@link org.apache.shale.clay.config.beans.ComponentBean}.
155 * </p>
156 *
157 * @param attributesNode markup
158 * @param target child config bean
159 */
160 protected void addValidatorVar(Node attributesNode, ComponentBean target) {
161 Iterator ci = attributesNode.getChildren().iterator();
162 while (ci.hasNext()) {
163 Node child = (Node) ci.next();
164 if (child.isWellFormed() && child.getName() != null
165 && child.getName().equals("validatorVar")) {
166
167 String name = (String) child.getAttributes().get("name");
168 String value = (String) child.getAttributes().get("value");
169 String bindingType = (String) child.getAttributes().get("bindingType");
170
171 AttributeBean attr = target.getAttribute(name);
172 if (attr != null) {
173 createAttribute(attr, value, target);
174 } else {
175 attr = new AttributeBean();
176 attr.setName(name);
177 attr.setValue(value);
178 attr.setBindingType(bindingType);
179 target.addAttribute(attr);
180 }
181 }
182 }
183 }
184
185 /***
186 * @inheritDoc
187 * @param node markup
188 * @param target child config bean
189 */
190 protected void addValidator(Node node, ElementBean target) {
191 ValidatorBean targetValidator = new ValidatorBean();
192
193
194 Builder tmpBuilder = getBuilder(node);
195 ElementBean tmp = tmpBuilder.createElement(node);
196
197 String jsfid = tmp.getJsfid();
198 targetValidator.setJsfid(jsfid);
199
200 String validatorId = (String) node.getAttributes().get("validatorId");
201 if (validatorId != null) {
202 targetValidator.setComponentType(tagsUtil.evalString(validatorId));
203 }
204
205
206 if (node.getAttributes().containsKey("extends") || !jsfid.equals("validator")) {
207 realizeComponent(node, targetValidator);
208 }
209
210
211 target.addValidator(targetValidator);
212
213 if (node.getName().equals("commonsValidator")) {
214
215
216
217 String type = (String) node.getAttributes().get("type");
218 targetValidator.setJsfid((String) validatorsByType.get(type));
219
220
221 addValidatorVar(node, targetValidator);
222 }
223
224 }
225
226 /***
227 * @inheritDoc
228 * @param node markup
229 * @param target child config bean
230 */
231 protected void addActionListener(Node node, ElementBean target) {
232 ActionListenerBean targetActionListener = new ActionListenerBean();
233
234
235 Builder tmpBuilder = getBuilder(node);
236 ElementBean tmp = tmpBuilder.createElement(node);
237
238 String jsfid = tmp.getJsfid();
239 targetActionListener.setJsfid(jsfid);
240
241 String type = (String) node.getAttributes().get("type");
242 if (type != null) {
243 targetActionListener.setComponentType(tagsUtil.evalString(type));
244 }
245
246
247 if (node.getAttributes().containsKey("extends") || !jsfid.equals("actionListener")) {
248 realizeComponent(node, targetActionListener);
249 }
250
251 target.addActionListener(targetActionListener);
252
253 }
254
255 /***
256 * @inheritDoc
257 * @param node markup
258 * @param target child config bean
259 */
260 protected void addValueChangeListener(Node node, ElementBean target) {
261 ValueChangeListenerBean targetValueChangeListener = new ValueChangeListenerBean();
262
263
264 Builder tmpBuilder = getBuilder(node);
265 ElementBean tmp = tmpBuilder.createElement(node);
266
267 String jsfid = tmp.getJsfid();
268 targetValueChangeListener.setJsfid(jsfid);
269
270 String type = (String) node.getAttributes().get("type");
271 if (type != null) {
272 targetValueChangeListener.setComponentType(tagsUtil.evalString(type));
273 }
274
275
276 if (node.getAttributes().containsKey("extends") || !jsfid.equals("valueChangeListener")) {
277 realizeComponent(node, targetValueChangeListener);
278 }
279
280
281 target.addValueChangeListener(targetValueChangeListener);
282 }
283
284 /***
285 * <p>Adds markup <clay:symbol> to the <code>target</code>
286 * {@link org.apache.shale.clay.config.beans.ElementBean}.
287 * </p>
288 *
289 * @param node markup
290 * @param target child config bean
291 */
292 protected void addSymbol(Node node, ElementBean target) {
293 String value = (String) node.getAttributes().get("value");
294 String name = (String) node.getAttributes().get("name");
295 if (name != null && name.length() > 0) {
296 SymbolBean symbol = new SymbolBean();
297 StringBuffer tmp = new StringBuffer(name);
298 if (tmp.charAt(0) != '@') {
299 tmp.insert(0, '@');
300 }
301
302 symbol.setName(tmp.toString());
303 symbol.setValue(value);
304 target.addSymbol(symbol);
305 }
306 }
307
308 /***
309 * <p>Adds markup <f:attribute> to the <code>target</code>
310 * {@link org.apache.shale.clay.config.beans.ElementBean}.
311 * </p>
312 *
313 * @param node markup
314 * @param target child config bean
315 */
316 protected void addAttribute(Node node, ElementBean target) {
317 String name = (String) target.getAttributes().get("name");
318 String value = (String) target.getAttributes().get("value");
319
320 AttributeBean attr = target.getAttribute(name);
321 if (attr != null) {
322 createAttribute(attr, value, target);
323 } else {
324 attr = new AttributeBean();
325 attr.setName(name);
326 attr.setValue(value);
327 attr.setBindingType(AttributeBean.BINDING_TYPE_EARLY);
328 target.addAttribute(attr);
329 }
330 }
331
332 /***
333 * <p>Adds markup <f:facet> to the <code>target</code>'s
334 * child {@link org.apache.shale.clay.config.beans.ElementBean}.
335 * </p>
336 *
337 * @param node markup
338 * @param target child config bean
339 */
340 protected void addFacet(Node node, ElementBean target) {
341 String facetName = (String) node.getAttributes().get("name");
342 Iterator ci = node.getChildren().iterator();
343
344
345 while (ci.hasNext()) {
346 Node child = (Node) ci.next();
347 if (child.isWellFormed()) {
348 Builder childBuilder = getBuilder(child);
349 ElementBean nextTarget = childBuilder.createElement(child);
350 nextTarget.setFacetName(facetName);
351 target.addChild(nextTarget);
352 childBuilder.encode(child, nextTarget, nextTarget);
353 break;
354 }
355 }
356 }
357
358
359 /***
360 * <p>Build's a <code>target</code> {@link ElementBean} from a {@link Node}. The
361 * following child nodes are handles outside of the <code>encodeChildren</code>
362 * method: symbol, facet, attribute, convert, validate, actionListener,
363 * and valueChangeListener.
364 * </p>
365 *
366 * @param node markup
367 * @param target child config bean
368 * @param root parent config bean
369 */
370 protected void encodeBegin(Node node, ElementBean target, ComponentBean root) {
371 assignNode(node, target);
372
373 List deleteList = new ArrayList();
374 Iterator ci = node.getChildren().iterator();
375 next: while (ci.hasNext()) {
376 Node child = (Node) ci.next();
377 if (child.isWellFormed() && child.getName() != null) {
378 if (child.getName().equals("symbol")) {
379 addSymbol(child, target);
380 deleteList.add(child);
381 } else if (child.getName().equals("facet")) {
382 addFacet(child, target);
383 deleteList.add(child);
384 } else if (child.getName().equals("attribute")) {
385 addAttribute(child, target);
386 deleteList.add(child);
387 } else if (child.getName().startsWith("convert")) {
388 addConverter(child, target);
389 deleteList.add(child);
390 } else if (child.getName().startsWith("validate")
391 || child.getName().startsWith("validator")
392 || child.getName().startsWith("commonsValidator")) {
393 addValidator(child, target);
394 deleteList.add(child);
395 } else if (child.getName().equals("actionListener")) {
396 addActionListener(child, target);
397 deleteList.add(child);
398 } else if (child.getName().equals("valueChangeListener")) {
399 addValueChangeListener(child, target);
400 deleteList.add(child);
401 }
402 } else {
403 if (node.getName() != null && node.getName().equals("verbatim")) {
404 continue next;
405 }
406 if (child.isComment() || isNodeWhitespace(child)) {
407
408 deleteList.add(child);
409 }
410 }
411 }
412
413 ci = deleteList.iterator();
414 while (ci.hasNext()) {
415 node.getChildren().remove(ci.next());
416 }
417
418 }
419
420 /***
421 * <p>Returns the <code>jsfid</code> from the {@link Node} The <code>extends</code>
422 * attribute is giving the first order of evaluation. If empty, the <code>node</code>'s
423 * name is assigned to the jsfid.</p>
424 *
425 * @param node markup
426 * @return jsfid
427 */
428 protected String getJsfid(Node node) {
429 StringBuffer jsfid = new StringBuffer();
430 if (node.getAttributes().containsKey("extends")) {
431 jsfid.append(node.getAttributes().get("extends"));
432 } else {
433 jsfid.append(node.getName());
434
435
436
437
438
439 String prefix = getPrefix();
440 if (prefix == null) {
441 prefix = node.getQname();
442 }
443 if (prefix != null) {
444 jsfid.insert(0, ':');
445 jsfid.insert(0, prefix);
446 }
447 }
448
449
450 return jsfid.toString();
451 }
452
453 /***
454 * <p>Returns the {@link org.apache.shale.clay.parser.builder.Builder} that
455 * is assigned the task of converting the html node to a corresponding component
456 * metadata used to construct a JSF resource.</p>
457 *
458 * @param node markup node
459 * @return builder that maps markup to config beans
460 */
461 public Builder getBuilder(Node node) {
462 return BuilderFactory.getRenderer(node);
463 }
464
465 }