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