Coverage Report - javax.faces.component.UIViewParameter
 
Classes in this File Line Coverage Branch Coverage Complexity
UIViewParameter
32%
25/78
14%
6/42
2.778
UIViewParameter$PropertyKeys
100%
2/2
N/A
2.778
UIViewParameter$Reference
0%
0/10
0%
0/2
2.778
 
 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  
 import java.util.concurrent.ConcurrentHashMap;
 23  
 import java.util.logging.Level;
 24  
 import java.util.logging.Logger;
 25  
 
 26  
 import javax.el.ValueExpression;
 27  
 import javax.faces.FactoryFinder;
 28  
 import javax.faces.application.FacesMessage;
 29  
 import javax.faces.context.FacesContext;
 30  
 import javax.faces.convert.Converter;
 31  
 import javax.faces.convert.ConverterException;
 32  
 import javax.faces.render.RenderKit;
 33  
 import javax.faces.render.RenderKitFactory;
 34  
 import javax.faces.render.Renderer;
 35  
 
 36  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
 37  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
 38  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
 39  
 
 40  
 /**
 41  
  * 
 42  
  * TODO: documentation on jsp and pld are not the same. It appear two
 43  
  * params: maxlength and for, but no property getter and setter founded here. 
 44  
  * If maxlength is used, we can put something like this: 
 45  
  * JSFJspProperty(name = "maxlength", returnType = "java.lang.String")
 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",
 52  
                 longDesc = "The max number or characters allowed for this param")
 53  
 public class UIViewParameter extends UIInput
 54  
 {
 55  2
     private static final Logger log = Logger.getLogger(UIViewParameter.class.getName());
 56  
     public static final String COMPONENT_FAMILY = "javax.faces.ViewParameter";
 57  
     public static final String COMPONENT_TYPE = "javax.faces.ViewParameter";
 58  
 
 59  
     private static final String DELEGATE_FAMILY = UIInput.COMPONENT_FAMILY;
 60  
     private static final String DELEGATE_RENDERER_TYPE = "javax.faces.Text";
 61  
     
 62  2
     private static ConcurrentHashMap<ClassLoader,Renderer> delegateRendererMap = 
 63  
         new ConcurrentHashMap<ClassLoader,Renderer>();
 64  
 
 65  
     public UIViewParameter()
 66  4
     {
 67  4
         setRendererType(null);
 68  4
     }
 69  
 
 70  
     @Override
 71  
     public String getFamily()
 72  
     {
 73  0
         return COMPONENT_FAMILY;
 74  
     }
 75  
 
 76  
     @Override
 77  
     public void decode(FacesContext context)
 78  
     {
 79  
         // Override behavior from superclass to pull a value from the incoming request parameter map under the 
 80  
         // name given by getName() and store it with a call to UIInput.setSubmittedValue(java.lang.Object).
 81  2
         String value = context.getExternalContext().getRequestParameterMap().get(getName());
 82  
         
 83  
         // only apply the value if it is non-null (otherwise postbacks 
 84  
         // to a view with view parameters would not work correctly)
 85  2
         if (value != null)
 86  
         {
 87  0
             setSubmittedValue(value);
 88  
         }
 89  2
     }
 90  
 
 91  
     @Override
 92  
     public void encodeAll(FacesContext context) throws IOException
 93  
     {
 94  0
         if (context == null) 
 95  
         {
 96  0
             throw new NullPointerException();
 97  
         }
 98  0
         setSubmittedValue(getStringValue(context));
 99  0
     }
 100  
 
 101  
     public String getName()
 102  
     {
 103  4
         return (String) getStateHelper().eval(PropertyKeys.name);
 104  
     }
 105  
 
 106  
     public String getStringValue(FacesContext context)
 107  
     {
 108  0
         if (getValueExpression ("value") != null) 
 109  
         {
 110  
             // Value specified as an expression, so do the conversion.
 111  
             
 112  0
             return getStringValueFromModel (context);
 113  
         }
 114  
         
 115  
         // Otherwise, just return the local value.
 116  
         
 117  0
         return ((String) this.getLocalValue());
 118  
     }
 119  
 
 120  
     public String getStringValueFromModel(FacesContext context) throws ConverterException
 121  
     {
 122  0
         ValueExpression ve = getValueExpression ("value");
 123  
         Converter converter;
 124  
         Object value;
 125  
         
 126  0
         if (ve == null) 
 127  
         {
 128  
             // No value expression, return null.
 129  0
             return null;
 130  
         }
 131  
         
 132  0
         value = ve.getValue (context.getELContext());
 133  
         
 134  0
         if (value instanceof String) 
 135  
         {
 136  
             // No need to convert.
 137  0
             return ((String) value);
 138  
         }
 139  
         
 140  0
         converter = getConverter();
 141  
         
 142  0
         if (converter == null) 
 143  
         {
 144  0
             if (value == null) 
 145  
             {
 146  
                 // No converter, no value, return null.
 147  0
                 return null;
 148  
             }
 149  
             
 150  
             // See if we can create the converter from the value type.
 151  
             
 152  0
             converter = context.getApplication().createConverter (value.getClass());
 153  
             
 154  0
             if (converter == null) 
 155  
             {
 156  
                 // Only option is to call toString().
 157  
                 
 158  0
                 return value.toString();
 159  
             }
 160  
         }
 161  
         
 162  0
         return converter.getAsString (context, this, value);
 163  
     }
 164  
 
 165  
     @JSFProperty(tagExcluded=true)
 166  
     @Override
 167  
     public boolean isImmediate()
 168  
     {
 169  0
         return false;
 170  
     }
 171  
     
 172  
     @JSFProperty(tagExcluded=true)
 173  
     @Override
 174  
     public boolean isRendered()
 175  
     {
 176  0
         return super.isRendered();
 177  
     }
 178  
     
 179  
     @Override
 180  
     public void processValidators(FacesContext context)
 181  
     {
 182  2
         if (context == null) 
 183  
         {
 184  0
             throw new NullPointerException ("context");
 185  
         }
 186  
         
 187  
         // If value is null and required is set, validation fails.
 188  
         
 189  2
         if ((getSubmittedValue() == null) && isRequired()) 
 190  
         {
 191  
             FacesMessage message;
 192  2
             String required = getRequiredMessage();
 193  
             
 194  2
             if (required != null) 
 195  
             {
 196  0
                 message = new FacesMessage (FacesMessage.SEVERITY_ERROR, required, required);
 197  
             }
 198  
             else 
 199  
             {
 200  2
                 Object label = _MessageUtils.getLabel (context, this);
 201  
                 
 202  2
                 message = _MessageUtils.getMessage (context, context.getViewRoot().getLocale(),
 203  
                      FacesMessage.SEVERITY_ERROR, REQUIRED_MESSAGE_ID, new Object[] { label });
 204  
             }
 205  
             
 206  2
             setValid (false);
 207  
             
 208  2
             context.addMessage (getClientId (context), message);
 209  2
             context.validationFailed();
 210  2
             context.renderResponse();
 211  
             
 212  2
             return;
 213  
         }
 214  
         
 215  0
         super.processValidators (context);
 216  0
     }
 217  
     
 218  4
     enum PropertyKeys
 219  
     {
 220  2
         name
 221  
     }
 222  
     
 223  
     public void setName(String name)
 224  
     {
 225  4
         getStateHelper().put(PropertyKeys.name, name );
 226  4
     }
 227  
 
 228  
     @Override
 229  
     public void updateModel(FacesContext context)
 230  
     {
 231  0
         super.updateModel(context);
 232  
         
 233  
         // Put name in request map if value is not a value expression, is valid, and local
 234  
         // value was set.
 235  
         
 236  0
         if ((getValueExpression ("value") == null) && isValid() && isLocalValueSet()) 
 237  
         {
 238  0
             context.getExternalContext().getRequestMap().put (getName(), getLocalValue());
 239  
         }
 240  0
     }
 241  
 
 242  
     @Override
 243  
     protected Object getConvertedValue(FacesContext context, Object submittedValue)
 244  
     {
 245  0
         return getDelegateRenderer(context).getConvertedValue(context, this, submittedValue);
 246  
     }
 247  
 
 248  
     private static Renderer getDelegateRenderer(FacesContext context)
 249  
     {
 250  0
         ClassLoader classLoader = _ClassUtils.getContextClassLoader();
 251  0
         Renderer delegateRenderer = delegateRendererMap.get(classLoader);
 252  0
         if(delegateRenderer == null)
 253  
         {
 254  0
             RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 255  0
             RenderKit kit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);
 256  
 
 257  0
             delegateRenderer = kit.getRenderer(DELEGATE_FAMILY, DELEGATE_RENDERER_TYPE);
 258  0
             delegateRendererMap.put(classLoader, delegateRenderer);
 259  
         }
 260  
 
 261  0
         return delegateRenderer;
 262  
     }
 263  
 
 264  
     /**
 265  
      * The idea of this method is to be called from AbstractFacesInitializer.
 266  
      */
 267  
     @SuppressWarnings("unused")
 268  
     private static void releaseRenderer() 
 269  
     {
 270  0
         if (log.isLoggable(Level.FINEST))
 271  
         {
 272  0
             log.finest("releaseRenderer rendererMap -> " + delegateRendererMap.toString());
 273  
         }
 274  
         
 275  
         
 276  0
         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 277  
         
 278  0
         if (log.isLoggable(Level.FINEST))
 279  
         {
 280  0
             log.finest("releaseRenderer classLoader -> " + classLoader.toString() );
 281  0
             log.finest("releaseRenderer renderer -> " + delegateRendererMap.get(classLoader));
 282  
         }
 283  
         
 284  
         
 285  0
         delegateRendererMap.remove(classLoader);
 286  
         
 287  0
         if (log.isLoggable(Level.FINEST))
 288  
         {
 289  0
             log.finest("releaseRenderer renderMap -> " + delegateRendererMap.toString());
 290  
         }
 291  
         
 292  0
     }
 293  
 
 294  
     @Override
 295  
     protected FacesContext getFacesContext()
 296  
     {
 297  
         //In theory the parent most of the times has 
 298  
         //the cached FacesContext instance, because this
 299  
         //element is purely logical, and the parent is the one
 300  
         //where encodeXXX was invoked. But only limit the
 301  
         //search to the closest parent.
 302  4
         UIComponent parent = getParent();
 303  4
         if (parent != null && parent.isCachedFacesContext())
 304  
         {
 305  0
             return parent.getFacesContext();
 306  
         }
 307  
         else
 308  
         {
 309  4
             return super.getFacesContext();
 310  
         }
 311  
     }
 312  
 
 313  
     /**
 314  
      * @since 2.0
 315  
      */
 316  
     public static class Reference
 317  
     {
 318  
         private int _index;
 319  
         private UIViewParameter _param;
 320  
         private Object _state;
 321  
         private String _viewId;
 322  
 
 323  
         public Reference(FacesContext context, UIViewParameter param, int indexInParent,
 324  
                          String viewIdAtTimeOfConstruction)
 325  0
         {
 326  
             // This constructor cause the StateHolder.saveState(javax.faces.context.FacesContext) method
 327  
             // to be called on argument UIViewParameter.
 328  0
             _param = param;
 329  0
             _viewId = viewIdAtTimeOfConstruction;
 330  0
             _index = indexInParent;
 331  0
             _state = param.saveState(context);
 332  0
         }
 333  
 
 334  
         public UIViewParameter getUIViewParameter(FacesContext context)
 335  
         {
 336  
             // If the current viewId is the same as the viewId passed to our constructor
 337  0
             if (context.getViewRoot().getViewId().equals(_viewId))
 338  
             {
 339  
                 // use the index passed to the constructor to find the actual UIViewParameter instance and return it.
 340  
                 // FIXME: How safe is that when dealing with component trees altered by applications?
 341  0
                 return (UIViewParameter) _param.getParent().getChildren().get(_index);
 342  
             }
 343  
             else
 344  
             {
 345  
                 // Otherwise, call StateHolder.restoreState(javax.faces.context.FacesContext, java.lang.Object) on
 346  
                 // the saved state and return the result.
 347  0
                 _param.restoreState(context, _state);
 348  
 
 349  0
                 return _param;
 350  
             }
 351  
         }
 352  
     }
 353  
 }