View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package javax.faces.component;
20  
21  import java.io.IOException;
22  
23  import javax.el.ValueExpression;
24  import javax.faces.FactoryFinder;
25  import javax.faces.application.FacesMessage;
26  import javax.faces.context.FacesContext;
27  import javax.faces.convert.Converter;
28  import javax.faces.convert.ConverterException;
29  import javax.faces.render.RenderKit;
30  import javax.faces.render.RenderKitFactory;
31  import javax.faces.render.Renderer;
32  
33  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
34  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
35  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
36  
37  /**
38   * 
39   * TODO: documentation on jsp and pld are not the same. It appear two
40   * params: maxlength and for, but no property getter and setter founded here. 
41   * If maxlength is used, we can put something like this: 
42   * JSFJspProperty(name = "maxlength", returnType = "java.lang.String")
43   * 
44   * @author Simon Lessard (latest modification by $Author: lu4242 $)
45   * @version $Revision: 955808 $ $Date: 2010-06-17 19:58:34 -0500 (Thu, 17 Jun 2010) $
46   * 
47   * @since 2.0
48   */
49  @JSFComponent(name = "f:viewParam", bodyContent = "JSP", 
50          tagClass = "org.apache.myfaces.taglib.core.ViewParamTag")
51  @JSFJspProperty(name = "maxlength", returnType = "int", longDesc = "The max number or characters allowed for this param")
52  public class UIViewParameter extends UIInput
53  {
54      public static final String COMPONENT_FAMILY = "javax.faces.ViewParameter";
55      public static final String COMPONENT_TYPE = "javax.faces.ViewParameter";
56  
57      private static final String DELEGATE_FAMILY = UIInput.COMPONENT_FAMILY;
58      private static final String DELEGATE_RENDERER_TYPE = "javax.faces.Text";
59      
60      private static Renderer _delegateRenderer;
61  
62      public UIViewParameter()
63      {
64          setRendererType(null);
65      }
66  
67      @Override
68      public String getFamily()
69      {
70          return COMPONENT_FAMILY;
71      }
72  
73      @Override
74      public void decode(FacesContext context)
75      {
76          // Override behavior from superclass to pull a value from the incoming request parameter map under the 
77          // name given by getName() and store it with a call to UIInput.setSubmittedValue(java.lang.Object).
78          String value = context.getExternalContext().getRequestParameterMap().get(getName());
79          
80          // only apply the value if it is non-null (otherwise postbacks 
81          // to a view with view parameters would not work correctly)
82          if (value != null)
83          {
84              setSubmittedValue(value);
85          }
86      }
87  
88      @Override
89      public void encodeAll(FacesContext context) throws IOException
90      {
91          if (context == null) 
92          {
93              throw new NullPointerException();
94          }
95          setSubmittedValue(getStringValue(context));
96      }
97  
98      public String getName()
99      {
100         return (String) getStateHelper().get(PropertyKeys.name);
101     }
102 
103     public String getStringValue(FacesContext context)
104     {
105         if (getValueExpression ("value") != null) 
106         {
107             // Value specified as an expression, so do the conversion.
108             
109             return getStringValueFromModel (context);
110         }
111         
112         // Otherwise, just return the local value.
113         
114         return ((String) this.getLocalValue());
115     }
116 
117     public String getStringValueFromModel(FacesContext context) throws ConverterException
118     {
119         ValueExpression ve = getValueExpression ("value");
120         Converter converter;
121         Object value;
122         
123         if (ve == null) 
124         {
125             // No value expression, return null.
126             return null;
127         }
128         
129         value = ve.getValue (context.getELContext());
130         
131         if (value instanceof String) 
132         {
133             // No need to convert.
134             return ((String) value);
135         }
136         
137         converter = getConverter();
138         
139         if (converter == null) 
140         {
141             if (value == null) 
142             {
143                 // No converter, no value, return null.
144                 return null;
145             }
146             
147             // See if we can create the converter from the value type.
148             
149             converter = context.getApplication().createConverter (value.getClass());
150             
151             if (converter == null) 
152             {
153                 // Only option is to call toString().
154                 
155                 return value.toString();
156             }
157         }
158         
159         return converter.getAsString (context, this, value);
160     }
161 
162     @Override
163     public String getSubmittedValue()
164     {
165         return (String)super.getSubmittedValue();
166     }
167 
168     @JSFProperty(tagExcluded=true)
169     @Override
170     public boolean isImmediate()
171     {
172         return false;
173     }
174     
175     @JSFProperty(tagExcluded=true)
176     @Override
177     public boolean isRendered()
178     {
179         return super.isRendered();
180     }
181     
182     @Override
183     public void processValidators(FacesContext context)
184     {
185         if (context == null) 
186         {
187             throw new NullPointerException ("context");
188         }
189         
190         // If value is null and required is set, validation fails.
191         
192         if ((getSubmittedValue() == null) && isRequired()) 
193         {
194             FacesMessage message;
195             String required = getRequiredMessage();
196             
197             if (required != null) 
198             {
199                 message = new FacesMessage (FacesMessage.SEVERITY_ERROR, required, required);
200             }
201             else 
202             {
203                 Object label = _MessageUtils.getLabel (context, this);
204                 
205                 message = _MessageUtils.getMessage (context, context.getViewRoot().getLocale(),
206                      FacesMessage.SEVERITY_ERROR, REQUIRED_MESSAGE_ID, new Object[] { label });
207             }
208             
209             setValid (false);
210             
211             context.addMessage (getClientId (context), message);
212             context.validationFailed();
213             context.renderResponse();
214             
215             return;
216         }
217         
218         super.processValidators (context);
219     }
220     
221     enum PropertyKeys
222     {
223         name
224     }
225     
226     public void setName(String name)
227     {
228         getStateHelper().put(PropertyKeys.name, name );
229     }
230 
231     @Override
232     public void updateModel(FacesContext context)
233     {
234         super.updateModel(context);
235         
236         // Put name in request map if value is not a value expression, is valid, and local
237         // value was set.
238         
239         if ((getValueExpression ("value") == null) && isValid() && isLocalValueSet()) 
240         {
241             context.getExternalContext().getRequestMap().put (getName(), getLocalValue());
242         }
243     }
244 
245     @Override
246     protected Object getConvertedValue(FacesContext context, Object submittedValue)
247     {
248         return getDelegateRenderer(context).getConvertedValue(context, this, submittedValue);
249     }
250 
251     private static Renderer getDelegateRenderer(FacesContext context)
252     {
253         if (_delegateRenderer == null)
254         {
255             RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
256             RenderKit kit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);
257 
258             _delegateRenderer = kit.getRenderer(DELEGATE_FAMILY, DELEGATE_RENDERER_TYPE);
259         }
260 
261         return _delegateRenderer;
262     }
263 
264     /**
265      * @author Simon Lessard (latest modification by $Author: lu4242 $)
266      * @version $Revision: 955808 $ $Date: 2010-06-17 19:58:34 -0500 (Thu, 17 Jun 2010) $
267      * 
268      * @since 2.0
269      */
270     public static class Reference
271     {
272         private int _index;
273         private UIViewParameter _param;
274         private Object _state;
275         private String _viewId;
276 
277         public Reference(FacesContext context, UIViewParameter param, int indexInParent,
278                          String viewIdAtTimeOfConstruction)
279         {
280             // This constructor cause the StateHolder.saveState(javax.faces.context.FacesContext) method
281             // to be called on argument UIViewParameter.
282             _param = param;
283             _viewId = viewIdAtTimeOfConstruction;
284             _index = indexInParent;
285             _state = param.saveState(context);
286         }
287 
288         public UIViewParameter getUIViewParameter(FacesContext context)
289         {
290             // If the current viewId is the same as the viewId passed to our constructor
291             if (context.getViewRoot().getViewId().equals(_viewId))
292             {
293                 // use the index passed to the constructor to find the actual UIViewParameter instance and return it.
294                 // FIXME: How safe is that when dealing with component trees altered by applications?
295                 return (UIViewParameter) _param.getParent().getChildren().get(_index);
296             }
297             else
298             {
299                 // Otherwise, call StateHolder.restoreState(javax.faces.context.FacesContext, java.lang.Object) on
300                 // the saved state and return the result.
301                 _param.restoreState(context, _state);
302 
303                 return _param;
304             }
305         }
306     }
307 }