Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
UIOutput |
|
| 3.5384615384615383;3.538 | ||||
UIOutput$PropertyKeys |
|
| 3.5384615384615383;3.538 |
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 | 382 | { |
45 | 382 | setRendererType("javax.faces.Text"); |
46 | 382 | } |
47 | ||
48 | @Override | |
49 | public String getFamily() | |
50 | { | |
51 | 132 | return COMPONENT_FAMILY; |
52 | } | |
53 | ||
54 | public Object getLocalValue() | |
55 | { | |
56 | 112 | 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 | 44 | return getStateHelper().eval(PropertyKeys.value); |
68 | } | |
69 | ||
70 | /** | |
71 | * The initial value of this component. | |
72 | */ | |
73 | public void setValue(Object value) | |
74 | { | |
75 | 138 | getStateHelper().put(PropertyKeys.value, value ); |
76 | 138 | } |
77 | ||
78 | /** | |
79 | * @since 2.2 | |
80 | */ | |
81 | public void resetValue() | |
82 | { | |
83 | 0 | setValue(null); |
84 | 0 | } |
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 | 80 | if (_converter != null) |
99 | { | |
100 | 30 | return _converter; |
101 | } | |
102 | 50 | ValueExpression expression = getValueExpression("converter"); |
103 | 50 | if (expression != null) |
104 | { | |
105 | 0 | return (Converter) expression.getValue(getFacesContext().getELContext()); |
106 | } | |
107 | 50 | return null; |
108 | } | |
109 | ||
110 | public void setConverter(Converter converter) | |
111 | { | |
112 | 88 | this._converter = converter; |
113 | 88 | if (initialStateMarked()) |
114 | { | |
115 | 10 | 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 | 88 | } |
120 | ||
121 | private boolean _isSetConverter() | |
122 | { | |
123 | 154 | Boolean value = (Boolean) getStateHelper().get(PropertyKeys.converterSet); |
124 | 154 | return value == null ? false : value; |
125 | } | |
126 | ||
127 | public void markInitialState() | |
128 | { | |
129 | 114 | super.markInitialState(); |
130 | 114 | if (_converter != null && |
131 | _converter instanceof PartialStateHolder) | |
132 | { | |
133 | 28 | ((PartialStateHolder)_converter).markInitialState(); |
134 | } | |
135 | 114 | } |
136 | ||
137 | public void clearInitialState() | |
138 | { | |
139 | 36 | if (initialStateMarked()) |
140 | { | |
141 | 36 | super.clearInitialState(); |
142 | 36 | if (_converter != null && |
143 | _converter instanceof PartialStateHolder) | |
144 | { | |
145 | 0 | ((PartialStateHolder)_converter).clearInitialState(); |
146 | } | |
147 | } | |
148 | 36 | } |
149 | ||
150 | 6 | enum PropertyKeys |
151 | { | |
152 | 2 | value |
153 | 2 | , converterSet |
154 | } | |
155 | ||
156 | @Override | |
157 | public Object saveState(FacesContext facesContext) | |
158 | { | |
159 | 76 | if (initialStateMarked()) |
160 | { | |
161 | 70 | Object parentSaved = super.saveState(facesContext); |
162 | 70 | Object converterSaved = null; |
163 | 70 | boolean nullDelta = true; |
164 | 70 | if (!_isSetConverter() && |
165 | _converter != null && | |
166 | _converter instanceof PartialStateHolder) | |
167 | { | |
168 | //Delta | |
169 | 10 | StateHolder holder = (StateHolder) _converter; |
170 | 10 | if (!holder.isTransient()) |
171 | { | |
172 | 8 | Object attachedState = holder.saveState(facesContext); |
173 | 8 | if (attachedState != null) |
174 | { | |
175 | 4 | nullDelta = false; |
176 | 4 | converterSaved = new _AttachedDeltaWrapper(_converter.getClass(), |
177 | attachedState); | |
178 | } | |
179 | 8 | } |
180 | else | |
181 | { | |
182 | 2 | nullDelta = false; |
183 | 2 | converterSaved = null; |
184 | } | |
185 | 10 | } |
186 | 60 | 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 | 24 | 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 | 16 | 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 | 16 | nullDelta = false; |
209 | } | |
210 | } | |
211 | ||
212 | 70 | if (parentSaved == null && nullDelta) |
213 | { | |
214 | //No values | |
215 | 14 | return null; |
216 | } | |
217 | 56 | else if (parentSaved != null && nullDelta) |
218 | { | |
219 | 34 | return new Object[]{parentSaved}; |
220 | } | |
221 | 22 | return new Object[]{parentSaved, converterSaved}; |
222 | } | |
223 | else | |
224 | { | |
225 | 6 | Object[] values = new Object[2]; |
226 | 6 | values[0] = super.saveState(facesContext); |
227 | 6 | values[1] = saveAttachedState(facesContext,_converter); |
228 | 6 | return values; |
229 | } | |
230 | } | |
231 | ||
232 | @Override | |
233 | public void restoreState(FacesContext facesContext, Object state) | |
234 | { | |
235 | 86 | if (state == null) |
236 | { | |
237 | 6 | return; |
238 | } | |
239 | ||
240 | 80 | Object[] values = (Object[])state; |
241 | 80 | 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 | 80 | if (values.length == 2) |
246 | { | |
247 | 58 | if (values[1] instanceof _AttachedDeltaWrapper) |
248 | { | |
249 | //Delta | |
250 | 4 | ((StateHolder)_converter).restoreState(facesContext, |
251 | ((_AttachedDeltaWrapper) values[1]).getWrappedStateObject()); | |
252 | } | |
253 | else | |
254 | { | |
255 | //Full | |
256 | 54 | _converter = (javax.faces.convert.Converter) restoreAttachedState(facesContext,values[1]); |
257 | } | |
258 | } | |
259 | 80 | } |
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 | } |