2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.util;
19  
20  import java.io.Serializable;
21  import javax.faces.application.Application;
22  import javax.faces.component.UIComponent;
23  import javax.faces.context.FacesContext;
24  import javax.faces.el.MethodBinding;
25  import javax.faces.el.ValueBinding;
26  import javax.faces.event.ActionEvent;
27  import javax.faces.event.ValueChangeEvent;
28  
29  /***
30   * <p>A utility class for JSF tags. An instance of this class is
31   *    specified as an application-scoped managed bean in <code>
32   *    faces-config.xml</code>, under the name
33   *    <code>org.apache.shale.TAG_UTILITY_BEAN</code>.
34   *    The <code>org.apache.shale.taglib.CommonsValidatorTag</code>
35   *    uses that managed bean.</p>
36   * <p>Nearly all of the methods of this class set a component attribute or
37   *    create a value- or method-binding, given a String representation
38   *    of the value. The methods check to see whether the value is a value
39   *    reference (ie. <code>#{...}</code>); if so, the methods set value
40   *    bindings or method bindings, as appropriate, for the component.</p>
41   *
42   * $Id: Tags.java 482453 2006-12-05 02:10:40Z rahul $
43   */
44  public class Tags {
45  
46  
47      /***
48       * <p>Sets the component's <code>attributeName</code> with the
49       *    given <code>attributeValue</code> as a <code>String</code>.</p>
50       *
51       * <p>If the <code>attributeValue</code> is <code>null</code>, do
52       *    nothing. If <code>attributeValue</code> is a value reference,
53       *    set a value binding for the component. Otherwise, store the
54       *    <code>attributeValue</code> in the component's attribute map.</p>
55       *
56       * @param component The JSF component
57       * @param attributeName The name of the attribute to set
58       * @param attributeValue The value of the attribute
59       */
60      public void setString(UIComponent component, String attributeName,
61              String attributeValue) {
62          if (attributeValue == null) {
63              return;
64          }
65          if (isValueReference(attributeValue)) {
66              setValueBinding(component, attributeName, attributeValue);
67          } else {
68              component.getAttributes().put(attributeName, attributeValue);
69          }
70      }
71  
72  
73      /***
74       * <p>Sets the component's <code>attributeName</code> with the
75       *    given <code>attributeValue</code> as a <code>Integer</code>.</p>
76       *
77       * <p>If the <code>attributeValue</code> is <code>null</code>, do
78       *    nothing. If <code>attributeValue</code> is a value reference,
79       *    set a value binding for the component. Otherwise, store the
80       *    <code>attributeValue</code> in the component's attribute map.</p>
81       *
82       * @param component The JSF component
83       * @param attributeName The name of the attribute to set
84       * @param attributeValue The value of the attribute
85       */
86      public void setInteger(UIComponent component,
87              String attributeName, String attributeValue) {
88          if (attributeValue == null) {
89              return;
90          }
91          if (isValueReference(attributeValue)) {
92              setValueBinding(component, attributeName, attributeValue);
93          } else {
94              component.getAttributes().put(attributeName,
95                      new Integer(attributeValue));
96          }
97      }
98  
99  
100     /***
101      * <p>Sets the component's <code>attributeName</code> with the
102      *    given <code>attributeValue</code> as a <code>Double</code>.</p>
103      *
104      * <p>If the <code>attributeValue</code> is <code>null</code>, do
105      *    nothing. If <code>attributeValue</code> is a value reference,
106      *    set a value binding for the component. Otherwise, store the
107      *    <code>attributeValue</code> in the component's attribute map.</p>
108      *
109      * @param component The JSF component
110      * @param attributeName The name of the attribute to set
111      * @param attributeValue The value of the attribute
112      */
113     public void setDouble(UIComponent component,
114             String attributeName, String attributeValue) {
115         if (attributeValue == null) {
116             return;
117         }
118         if (isValueReference(attributeValue)) {
119             setValueBinding(component, attributeName, attributeValue);
120         } else {
121             component.getAttributes().put(attributeName,
122                     new Double(attributeValue));
123         }
124     }
125 
126 
127     /***
128      * <p>Sets the component's <code>attributeName</code> with the
129      *    given <code>attributeValue</code> as a <code>Boolean</code>.</p>
130      *
131      * <p>If the <code>attributeValue</code> is <code>null</code>, do
132      *    nothing. If <code>attributeValue</code> is a value reference,
133      *    set a value binding for the component. Otherwise, store the
134      *    <code>attributeValue</code> in the component's attribute map.</p>
135      *
136      * @param component The JSF component
137      * @param attributeName The name of the attribute to set
138      * @param attributeValue The value of the attribute
139      */
140     public void setBoolean(UIComponent component,
141             String attributeName, String attributeValue) {
142         if (attributeValue == null) {
143             return;
144         }
145         if (isValueReference(attributeValue)) {
146             setValueBinding(component, attributeName, attributeValue);
147         } else {
148             component.getAttributes().put(attributeName,
149                     new Boolean(attributeValue));
150         }
151     }
152 
153 
154     /***
155      * <p>Sets the component's <code>attributeName</code> with the
156      *    given <code>attributeValue</code> as a <code>ValueBinding</code>.</p>
157      *
158      * <p>If the <code>attributeValue</code> is <code>null</code>, do
159      *    nothing. If <code>attributeValue</code> is a value reference,
160      *    set a value binding for the component. Otherwise, store the
161      *    <code>attributeValue</code> in the component's attribute map.</p>
162      *
163      * @param component The JSF component
164      * @param attributeName The name of the attribute to set
165      * @param attributeValue The value of the attribute
166      */
167     public void setValueBinding(UIComponent component, String attributeName,
168             String attributeValue) {
169         FacesContext context = FacesContext.getCurrentInstance();
170         Application app = context.getApplication();
171         ValueBinding vb = app.createValueBinding(attributeValue);
172         component.setValueBinding(attributeName, vb);
173     }
174 
175 
176     /***
177      * <p>Sets the component's <code>ActionListener</code>
178      *    by setting a method binding with the given attribute
179      *    value.</p>
180      *
181      * @param component The JSF component
182      * @param attributeValue The value of the attribute
183      */
184     public void setActionListener(UIComponent component, String attributeValue) {
185         setMethodBinding(component, "actionListener", attributeValue,
186                 new Class[] { ActionEvent.class });
187     }
188 
189 
190     /***
191      * <p>Sets the component's <code>ValueChangeListener</code>
192      *    by setting a method binding with the given attribute
193      *    value.</p>
194      *
195      * @param component The JSF component
196      * @param attributeValue The value of the attribute
197      */
198     public void setValueChangeListener(UIComponent component,
199             String attributeValue) {
200         setMethodBinding(component, "valueChangeListener", attributeValue,
201                 new Class[] { ValueChangeEvent.class });
202     }
203 
204 
205     /***
206      * <p>Sets the component's <code>Validator</code>
207      *    by setting a method binding with the given attribute
208      *    value.</p>
209      *
210      * @param component The JSF component
211      * @param attributeValue The value of the attribute
212      */
213     public void setValidator(UIComponent component,
214             String attributeValue) {
215         setMethodBinding(component, "validator", attributeValue,
216                 new Class[] { FacesContext.class, UIComponent.class, Object.class });
217     }
218 
219 
220     /***
221      * <p>Sets the component's <code>Action</code>
222      *    by setting a method binding with the given attribute
223      *    value.</p>
224      *
225      * @param component The JSF component
226      * @param attributeValue The value of the attribute
227      */
228     public void setAction(UIComponent component, String attributeValue) {
229         if (attributeValue == null) {
230             return;
231         }
232         if (isValueReference(attributeValue)) {
233             setMethodBinding(component, "action", attributeValue,
234                     new Class[] {});
235         } else {
236             MethodBinding mb = new ActionMethodBinding(attributeValue);
237             component.getAttributes().put("action", mb);
238         }
239     }
240 
241 
242     /***
243      * <p>Sets the component's <code>attributeName</code> with the
244      *    given <code>attributeValue</code> as a <code>MethodBinding</code>.</p>
245      *
246      * <p>If the <code>attributeValue</code> is <code>null</code>, do
247      *    nothing. If <code>attributeValue</code> is a value reference,
248      *    set a value binding for the component. Otherwise, store the
249      *    <code>attributeValue</code> in the component's attribute map.</p>
250      *
251      * @param component The JSF component
252      * @param attributeName The name of the attribute to set
253      * @param attributeValue The value of the attribute
254      * @param paramTypes Signature for method parameters
255      */
256     public void setMethodBinding(UIComponent component, String attributeName,
257             String attributeValue, Class[] paramTypes) {
258         if (attributeValue == null) {
259             return;
260         }
261         if (isValueReference(attributeValue)) {
262             FacesContext context = FacesContext.getCurrentInstance();
263             Application app = context.getApplication();
264             MethodBinding mb = app.createMethodBinding(attributeValue, paramTypes);
265             component.getAttributes().put(attributeName, mb);
266         }
267     }
268 
269 
270     /***
271      * <p>Evaluate the <code>expression</code>. If it's a value reference,
272      *    get the reference's value.
273      *    Otherwise, return the <code>expression</code>.</p>
274      *
275      * @param expression The expression
276      */
277     public Object eval(String expression) {
278         if (expression == null) {
279             return null;
280         }
281         if (isValueReference(expression)) {
282             FacesContext context = FacesContext.getCurrentInstance();
283             Application app = context.getApplication();
284             return app.createValueBinding(expression).getValue(context);
285         } else {
286             return expression;
287         }
288     }
289 
290 
291     /***
292      * <p>Evaluate the <code>expression</code>. If it's a value reference,
293      *    get the reference's value as a String.
294      *    Otherwise, return the <code>expression</code>.</p>
295      *
296      * @param expression The expression
297      */
298     public String evalString(String expression) {
299         if (expression == null) {
300             return null;
301         }
302         if (isValueReference(expression)) {
303             FacesContext context = FacesContext.getCurrentInstance();
304             Application app = context.getApplication();
305             return "" + app.createValueBinding(expression).getValue(context);
306         } else {
307             return expression;
308         }
309     }
310 
311 
312     /***
313      * <p>Evaluate the <code>expression</code> and return an <code>Integer</code>.</p>
314      *
315      * @param expression The expression
316      */
317     public Integer evalInteger(String expression) {
318         if (expression == null) {
319             return null;
320         }
321         if (isValueReference(expression)) {
322             FacesContext context = FacesContext.getCurrentInstance();
323             Application app = context.getApplication();
324             Object r = app.createValueBinding(expression).getValue(context);
325             if (r == null) {
326                 return null;
327             } else if (r instanceof Integer) {
328                 return (Integer) r;
329             } else {
330                 return new Integer(r.toString());
331             }
332         } else {
333             return new Integer(expression);
334         }
335     }
336 
337 
338     /***
339      * <p>Evaluate the <code>expression</code> and return a <code>Double</code>.</p>
340      *
341      * @param expression The expression
342      */
343     public Double evalDouble(String expression) {
344         if (expression == null) {
345             return null;
346         }
347         if (isValueReference(expression)) {
348             FacesContext context = FacesContext.getCurrentInstance();
349             Application app = context.getApplication();
350             Object r = app.createValueBinding(expression).getValue(context);
351             if (r == null) {
352                 return null;
353             } else if (r instanceof Double) {
354                 return (Double) r;
355             } else {
356                 return new Double(r.toString());
357             }
358         } else {
359             return new Double(expression);
360         }
361     }
362 
363 
364     /***
365      * <p>Evaluate the <code>expression</code> and return a <code>Boolean</code>.</p>
366      *
367      * @param expression The expression
368      */
369     public Boolean evalBoolean(String expression) {
370         if (expression == null) {
371             return null;
372         }
373         if (isValueReference(expression)) {
374             FacesContext context = FacesContext.getCurrentInstance();
375             Application app = context.getApplication();
376             Object r = app.createValueBinding(expression).getValue(context);
377             if (r == null) {
378                 return null;
379             } else if (r instanceof Boolean) {
380                 return (Boolean) r;
381             } else {
382                 return new Boolean(r.toString());
383             }
384         } else {
385             return new Boolean(expression);
386         }
387     }
388 
389 
390     /***
391      * <p>A method binding whose result is a canned string.</p>
392      *
393      */
394     private static class ActionMethodBinding
395             extends MethodBinding implements Serializable {
396 
397         private static final long serialVersionUID = -8155887531790127241L;
398         private String result;
399 
400         public ActionMethodBinding(String result) { this.result = result; }
401         public Object invoke(FacesContext context, Object params[]) {
402             return result;
403         }
404         public String getExpressionString() { return result; }
405         public Class getType(FacesContext context) { return String.class; }
406     }
407 
408 
409     /***
410      * <p>Return true if the specified string contains an EL expression.</p>
411      * 
412      * <p>This is taken almost verbatim from {@link javax.faces.webapp.UIComponentTag}
413      * in order to remove JSP dependencies from the renderers.</p>
414      *
415      * @param value String to be checked for being an expression
416      */
417     private boolean isValueReference(String value) {
418 
419         if (value == null) {
420             return false;
421         }
422 
423         int start = value.indexOf("#{");
424         if (start < 0) {
425             return false;
426         }
427 
428         int end = value.lastIndexOf('}');
429         return (end >= 0) && (start < end);
430     }
431 
432 
433 }