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  
22  import javax.el.ValueExpression;
23  import javax.faces.context.FacesContext;
24  import javax.faces.convert.Converter;
25  
26  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
27  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
28  
29  /**
30   * Displays a value to the user.
31   */
32  @JSFComponent(defaultRendererType = "javax.faces.Text")
33  public class UIOutput extends UIComponentBase implements ValueHolder
34  {
35      public static final String COMPONENT_TYPE = "javax.faces.Output";
36      public static final String COMPONENT_FAMILY = "javax.faces.Output";
37  
38      private Converter _converter;
39  
40      /**
41       * Construct an instance of the UIOutput.
42       */
43      public UIOutput()
44      {
45          setRendererType("javax.faces.Text");
46      }
47  
48      @Override
49      public String getFamily()
50      {
51          return COMPONENT_FAMILY;
52      }
53  
54      public Object getLocalValue()
55      {
56          return  getStateHelper().get(PropertyKeys.value);
57      }
58  
59      /**
60       * Gets The initial value of this component.
61       * 
62       * @return the new value value
63       */
64      @JSFProperty
65      public Object getValue()
66      {
67          return  getStateHelper().eval(PropertyKeys.value);
68      }
69  
70      /**
71       * The initial value of this component.
72       */
73      public void setValue(Object value)
74      {
75          getStateHelper().put(PropertyKeys.value, value );
76      }
77      
78      /**
79       * @since 2.2
80       */
81      public void resetValue()
82      {
83          setValue(null);
84      }
85  
86      /**
87       * An expression that specifies the Converter for this component.
88       * <p>
89       * The value can either be a static value (ID) or an EL expression. When a static id is
90       * specified, an instance of the converter type registered with that id is used. When this
91       * is an EL expression, the result of evaluating the expression must be an object that
92       * implements the Converter interface.
93       * </p>
94       */
95      @JSFProperty(partialStateHolder=true)
96      public Converter getConverter()
97      {
98          if (_converter != null)
99          {
100             return _converter;
101         }
102         ValueExpression expression = getValueExpression("converter");
103         if (expression != null)
104         {
105             return (Converter) expression.getValue(getFacesContext().getELContext());
106         }
107         return null;
108     }
109 
110     public void setConverter(Converter converter)
111     {
112         this._converter = converter;
113         if (initialStateMarked())
114         {
115             getStateHelper().put(PropertyKeys.converterSet,Boolean.TRUE);
116         }
117         // The argument converter must be inspected for the presence of the ResourceDependency annotation.
118         //_handleAnnotations(FacesContext.getCurrentInstance(), converter);
119     }
120     
121     private boolean _isSetConverter()
122     {
123         Boolean value = (Boolean) getStateHelper().get(PropertyKeys.converterSet);
124         return value == null ? false : value;
125     }
126     
127     public void markInitialState()
128     {
129         super.markInitialState();
130         if (_converter != null && 
131             _converter instanceof PartialStateHolder)
132         {
133             ((PartialStateHolder)_converter).markInitialState();
134         }
135     }
136     
137     public void clearInitialState()
138     {
139         if (initialStateMarked())
140         {
141             super.clearInitialState();
142             if (_converter != null && 
143                 _converter instanceof PartialStateHolder)
144             {
145                 ((PartialStateHolder)_converter).clearInitialState();
146             }
147         }
148     }
149     
150     enum PropertyKeys
151     {
152          value
153         , converterSet
154     }
155 
156     @Override
157     public Object saveState(FacesContext facesContext)
158     {
159         if (initialStateMarked())
160         {
161             Object parentSaved = super.saveState(facesContext);
162             Object converterSaved = null;
163             boolean nullDelta = true;
164             if (!_isSetConverter() &&
165                 _converter != null && 
166                 _converter instanceof PartialStateHolder)
167             {
168                 //Delta
169                 StateHolder holder = (StateHolder) _converter;
170                 if (!holder.isTransient())
171                 {
172                     Object attachedState = holder.saveState(facesContext);
173                     if (attachedState != null)
174                     {
175                         nullDelta = false;
176                         converterSaved = new _AttachedDeltaWrapper(_converter.getClass(),
177                             attachedState);
178                     }
179                 }
180                 else
181                 {
182                     nullDelta = false;
183                     converterSaved = null;
184                 }
185             }
186             else if (_isSetConverter() || _converter != null)
187             {
188                 // A converter that does not implement StateHolder does not need
189                 // to save/restore the state, so we can consider it inmutable.
190                 // If Call saveAttachedState(), keep the value, but do not set
191                 // nullDelta only if the converter was not set after markInitialState(),
192                 // so if the parent returns null, this part will return
193                 // null and when is restored, it will return null, but it prevents
194                 // add the attached object into the state.
195                 if (!_isSetConverter() && _converter != null &&
196                     !(_converter instanceof StateHolder))
197                 {
198                     //No op. Note converterSaved is not taken into account if
199                     //nullDelta is true.
200                 }
201                 else
202                 {
203                     //Full
204                     converterSaved = saveAttachedState(facesContext,_converter);
205                     // If _converter == null, setConverter() was called after
206                     // markInitialState(), set nullDelta to false and save the
207                     // null spot.
208                     nullDelta = false;
209                 }
210             }
211 
212             if (parentSaved == null && nullDelta)
213             {
214                 //No values
215                 return null;
216             }
217             else if (parentSaved != null && nullDelta)
218             {
219                 return new Object[]{parentSaved};
220             }
221             return new Object[]{parentSaved, converterSaved};
222         }
223         else
224         {
225             Object[] values = new Object[2];
226             values[0] = super.saveState(facesContext);
227             values[1] = saveAttachedState(facesContext,_converter);
228             return values;
229         } 
230     }
231 
232     @Override
233     public void restoreState(FacesContext facesContext, Object state)
234     {
235         if (state == null)
236         {
237             return;
238         }
239         
240         Object[] values = (Object[])state;
241         super.restoreState(facesContext,values[0]);
242         // Have values.length == 1 considers _converter is nullDelta, in that
243         // case, there is no need to do any changes, but note this will only work
244         // if UIOutput does not have any more StateHolder properties!.
245         if (values.length == 2)
246         {
247             if (values[1] instanceof _AttachedDeltaWrapper)
248             {
249                 //Delta
250                 ((StateHolder)_converter).restoreState(facesContext,
251                         ((_AttachedDeltaWrapper) values[1]).getWrappedStateObject());
252             }
253             else
254             {
255                 //Full
256                 _converter = (javax.faces.convert.Converter) restoreAttachedState(facesContext,values[1]);
257             }
258         }
259     }
260     
261     /*
262     void _handleAnnotations(FacesContext context, Object inspected)
263     {
264         if (inspected == null) {
265             return;
266         }
267         
268         ResourceDependency annotation = inspected.getClass().getAnnotation(ResourceDependency.class);
269         
270         if (annotation == null)
271         {
272             // If the ResourceDependency annotation is not present, the argument must be inspected for the presence 
273             // of the ResourceDependencies annotation. 
274             ResourceDependencies dependencies = inspected.getClass().getAnnotation(ResourceDependencies.class);
275             if (dependencies != null)
276             {
277                 // If the ResourceDependencies annotation is present, the action described in ResourceDependencies 
278                 // must be taken.
279                 for (ResourceDependency dependency : dependencies.value())
280                 {
281                     _handleResourceDependency(context, dependency);
282                 }
283             }
284         }
285         else
286         {
287             // If the ResourceDependency annotation is present, the action described in ResourceDependency must be 
288             // taken. 
289             _handleResourceDependency(context, annotation);
290         }
291     }
292     
293     private void _handleResourceDependency(FacesContext context, ResourceDependency annotation)
294     {
295         // If this annotation is not present on the class in question, no action must be taken. 
296         if (annotation != null)
297         {
298             Application application = context.getApplication();
299             
300             // Create a UIOutput instance by passing javax.faces.Output. to 
301             // Application.createComponent(java.lang.String).
302             UIOutput output = (UIOutput) application.createComponent(COMPONENT_TYPE);
303             
304             // Get the annotation instance from the class and obtain the values of the name, library, and 
305             // target attributes.
306             String name = annotation.name();
307             
308             // Obtain the renderer-type for the resource name by passing name to 
309             // ResourceHandler.getRendererTypeForResourceName(java.lang.String).
310             String rendererType = application.getResourceHandler().getRendererTypeForResourceName(name);
311             
312             // Call setRendererType on the UIOutput instance, passing the renderer-type.
313             output.setRendererType(rendererType);
314             
315             // Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
316             Map<String, Object> attributes = output.getAttributes();
317             
318             // Store the name into the attributes Map under the key "name".
319             attributes.put("name", name);
320             
321             // If library is the empty string, let library be null.
322             String library = annotation.library();
323             if (library != null && library.length() > 0)
324             {
325                 // If library is non-null, store it under the key "library".
326                 attributes.put("library", library);
327             }
328             
329             // If target is the empty string, let target be null.
330             String target = annotation.target();
331             if (target != null && target.length() > 0)
332             {
333                 // If target is non-null, store it under the key "target".
334                 attributes.put("target", target);
335             }
336             else
337             {
338                 // Otherwise, if target is null, call UIViewRoot.addComponentResource(javax.faces.context.FacesContext, 
339                 // javax.faces.component.UIComponent), passing the UIOutput instance as the second argument.
340                 context.getViewRoot().addComponentResource(context, output);
341             }
342         }
343     }
344     */
345 }