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  /*
19   * $Id: PropertyValueCommand.java 473039 2006-11-09 19:26:41Z gvanmatre $
20   */
21  package org.apache.shale.clay.component.chain;
22  
23  import java.util.Map;
24  
25  import javax.faces.component.UIComponent;
26  import javax.faces.context.FacesContext;
27  import javax.faces.convert.Converter;
28  import javax.faces.el.PropertyNotFoundException;
29  import javax.faces.el.ValueBinding;
30  
31  import org.apache.commons.chain.Command;
32  import org.apache.commons.chain.Context;
33  import org.apache.shale.clay.config.beans.AttributeBean;
34  import org.apache.shale.clay.config.beans.ComponentBean;
35  import org.apache.shale.util.ConverterHelper;
36  import org.apache.shale.util.PropertyHelper;
37  
38  /***
39   * <p>
40   * This is the catch all <code>Command</code> to handle all attributes that
41   * are not an "action", "actionListener", "validator" and "valueChangeListener".
42   * This <code>Command</code> is invoked from the
43   * {@link AssignPropertiesCommand} chain.
44   * <p>
45   */
46  public class PropertyValueCommand extends AbstractCommand implements Command {
47  
48      /***
49       * <p>Helper class to provide access to the properties of JavaBeans.</p>
50       */
51      private PropertyHelper propertyHelper = new PropertyHelper();
52  
53      /***
54       * <p>Helper class to provide access to by-type JavaServer Faces
55       * <code>Converter</code> capabilities.</p>
56       */
57      private ConverterHelper converterHelper = new ConverterHelper();
58  
59      /***
60       * <p>Sets a property value on the target component.  If the data
61       * type of the target bean property is not a String and the property
62       * value is a String, the data type is converted to the target type
63       * using the <code>ConverterHelper</code>.  The value is applied to
64       * the component using <code>PropertyHelper</code>.</p>
65       *
66       * @param context faces context
67       * @param target object with the property
68       * @param propertyName name of the target property
69       * @param propertyValue value of the target property
70       */
71      private void setProperty(FacesContext context, Object target, String propertyName, Object propertyValue) {
72          Class classz = null;
73          StringBuffer actualPropertyName = new StringBuffer(propertyName);
74  
75          try {
76              classz = propertyHelper.getType(target, actualPropertyName.toString());
77          } catch (PropertyNotFoundException e) {
78              if (propertyName.length() > "isX".length() && propertyName.startsWith("is")) {
79                 actualPropertyName.delete(0, 2);
80                 actualPropertyName.setCharAt(0, Character.toLowerCase(actualPropertyName.charAt(0)));
81  
82                 classz = propertyHelper.getType(target, actualPropertyName.toString());
83              } else {
84                 throw e;
85              }
86  
87          }
88  
89          if (classz != Object.class && classz != propertyValue.getClass()
90              && propertyValue.getClass() == String.class) {
91  
92              Object targetValue = converterHelper.asObject(context, classz, (String) propertyValue);
93              propertyHelper.setValue(target, actualPropertyName.toString(), targetValue);
94          } else {
95              propertyHelper.setValue(target, actualPropertyName.toString(), propertyValue);
96          }
97  
98      }
99  
100 
101     /***
102      * <p>
103      * Looks at the {@link AttributeBean} on the {@link ClayContext} to see
104      * if the value is a binding EL.  If it is not it just updates the component
105      * with the value.  If the attribute is a value binding expression, then a
106      * <code>ValueBinding</code> is created.  If the attribute uses early binding
107      * the <code>ValueBinding</code> is executed and result applied to the component.
108      * Otherwise, the binding expression is applied to the component in a prepared state.
109      * A <code>true</code> value is always returned because this is the default handler.
110      * </p>
111      *
112      * @param context common chains
113      * @return <code>true</code> if the chain is complete
114      * @exception Exception propagated up to the top of the chain
115      */
116     public boolean execute(Context context) throws Exception {
117 
118         boolean isFinal = true;
119 
120         ClayContext clayContext = (ClayContext) context;
121         if (clayContext == null) {
122             throw new NullPointerException(getMessages().getMessage("clay.null.clayContext"));
123         }
124         AttributeBean attributeBean = clayContext.getAttribute();
125         if (attributeBean == null) {
126             throw new NullPointerException(getMessages().getMessage("clay.null.attributeBean"));
127         }
128         Object child = clayContext.getChild();
129         if (child == null) {
130             throw new NullPointerException(getMessages().getMessage("clay.null.childComponent"));
131         }
132         ComponentBean displayElement = clayContext.getDisplayElement();
133         if (displayElement == null) {
134             throw new NullPointerException(getMessages().getMessage("clay.null.componentBean"));
135         }
136         FacesContext facesContext = clayContext.getFacesContext();
137         if (facesContext == null) {
138             throw new NullPointerException(getMessages().getMessage("clay.null.facesContext"));
139         }
140 
141         // don't try to set the binding attribute of anything but a component
142         if (attributeBean.getName().equals("binding")
143                 && !(child instanceof UIComponent)) {
144             return isFinal;
145 
146         }
147         // skip trying to set the converterId on a converter
148         if (attributeBean.getName().equals("converterId")
149                 && child instanceof Converter) {
150             return isFinal;
151         }
152         // replace all symbols returning the target attribute value
153         String expr = replaceMnemonic(clayContext);
154 
155         //exit if null or empty string
156         if (expr == null) {
157            return isFinal;
158         }
159 
160 
161         String bindingType = attributeBean.getBindingType();
162         if (bindingType == null) {
163             bindingType = AttributeBean.BINDING_TYPE_NONE;
164         }
165 
166         //contains expression language
167         boolean isEL = isValueReference(expr);
168         //use value binding
169         boolean isVB = ((bindingType.equals(AttributeBean.BINDING_TYPE_VALUE))
170                         && (child instanceof UIComponent));
171         //use early binding
172         boolean isEarly = bindingType.equals(AttributeBean.BINDING_TYPE_EARLY);
173 
174         if (isEL && isVB) {
175            getTagUtils().setValueBinding((UIComponent) child, attributeBean.getName(), expr);
176         } else if (isEL && isEarly) {
177             ValueBinding vb = facesContext.getApplication().createValueBinding(expr);
178             Object value = vb.getValue(facesContext);
179             try {
180                 setProperty(facesContext, child, attributeBean.getName(), value);
181             } catch (Exception e) {
182                  if (child instanceof UIComponent) {
183                    ((UIComponent) child).getAttributes().put(attributeBean.getName(), expr);
184                  } else {
185                     throw e;
186                  }
187              }
188         } else  {
189             try {
190                setProperty(facesContext, child, attributeBean.getName(), expr);
191             } catch (Exception e) {
192                 if (child instanceof UIComponent) {
193                   ((UIComponent) child).getAttributes().put(attributeBean.getName(), expr);
194                 } else {
195                    if (child.getClass().getName().equals("org.apache.shale.validator.CommonsValidator")) {
196                       Map vars = (Map) propertyHelper.getValue(child, "vars");
197                       //vars collection is like the components attributes
198                       //native support for shale components
199                       vars.put(attributeBean.getName(), expr);
200                    } else {
201                       throw e;
202                    }
203                 }
204             }
205         }
206 
207         return isFinal;
208     }
209 
210 }