Home » Mojarra-2.0.1 » javax » faces » component » [javadoc | source]

    1   /*
    2    * $Id: UIInput.java,v 1.96.8.1 2008/04/21 20:31:24 edburns Exp $
    3    */
    4   
    5   /*
    6    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    7    * 
    8    * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    9    * 
   10    * The contents of this file are subject to the terms of either the GNU
   11    * General Public License Version 2 only ("GPL") or the Common Development
   12    * and Distribution License("CDDL") (collectively, the "License").  You
   13    * may not use this file except in compliance with the License. You can obtain
   14    * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   15    * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   16    * language governing permissions and limitations under the License.
   17    * 
   18    * When distributing the software, include this License Header Notice in each
   19    * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   20    * Sun designates this particular file as subject to the "Classpath" exception
   21    * as provided by Sun in the GPL Version 2 section of the License file that
   22    * accompanied this code.  If applicable, add the following below the License
   23    * Header, with the fields enclosed by brackets [] replaced by your own
   24    * identifying information: "Portions Copyrighted [year]
   25    * [name of copyright owner]"
   26    * 
   27    * Contributor(s):
   28    * 
   29    * If you wish your version of this file to be governed by only the CDDL or
   30    * only the GPL Version 2, indicate your decision by adding "[Contributor]
   31    * elects to include this software in this distribution under the [CDDL or GPL
   32    * Version 2] license."  If you don't indicate a single choice of license, a
   33    * recipient has the option to distribute your version of this file under
   34    * either the CDDL, the GPL Version 2 or to extend the choice of license to
   35    * its licensees as provided above.  However, if you add GPL Version 2 code
   36    * and therefore, elected the GPL Version 2 license, then the option applies
   37    * only if the new code is made subject to such option by the copyright
   38    * holder.
   39    */
   40   
   41   package javax.faces.component;
   42   
   43   import java.util.Collection;
   44   import java.util.List;
   45   
   46   import java.util.Map;
   47   import javax.el.ELException;
   48   import javax.el.ValueExpression;
   49   import javax.faces.FacesException;
   50   import javax.faces.application.Application;
   51   import javax.faces.application.FacesMessage;
   52   import javax.faces.context.ExceptionHandler;
   53   import javax.faces.context.ExternalContext;
   54   import javax.faces.context.FacesContext;
   55   import javax.faces.convert.Converter;
   56   import javax.faces.convert.ConverterException;
   57   import javax.faces.el.MethodBinding;
   58   import javax.faces.event.ExceptionQueuedEvent;
   59   import javax.faces.event.ExceptionQueuedEventContext;
   60   import javax.faces.event.PhaseId;
   61   import javax.faces.event.ValueChangeEvent;
   62   import javax.faces.event.ValueChangeListener;
   63   import javax.faces.render.Renderer;
   64   import javax.faces.validator.BeanValidator;
   65   import javax.faces.validator.Validator;
   66   import javax.faces.validator.ValidatorException;
   67   
   68   /**
   69    * <p><span class="changed_modified_2_0"><strong>UIInput</strong></span>
   70    * is a {@link UIComponent} that represents a component that both
   71    * displays output to the user (like {@link UIOutput} components do) and
   72    * processes request parameters on the subsequent request that need to
   73    * be decoded.  There are no restrictions on the data type of the local
   74    * value, or the object referenced by the value binding expression (if
   75    * any); however, individual {@link javax.faces.render.Renderer}s will
   76    * generally impose restrictions on the type of data they know how to
   77    * display.</p> 
   78    *
   79    * <p>During the <em>Apply Request Values</em> phase
   80    * of the request processing lifecycle, the decoded value of this
   81    * component, usually but not necessarily a String, must be stored - but
   82    * not yet converted - using <code>setSubmittedValue()</code>.  If the
   83    * component wishes to indicate that no particular value was submitted,
   84    * it can either do nothing, or set the submitted value to
   85    * <code>null</code>.</p>
   86   
   87    * <p>By default, during the <em>Process Validators</em> phase of the
   88    * request processing lifecycle, the submitted value will be converted
   89    * to a typesafe object, and, if validation succeeds, stored as a local
   90    * value using <code>setValue()</code>.  However, if the
   91    * <code>immediate</code> property is set to <code>true</code>, this
   92    * processing will occur instead at the end of the <em>Apply Request
   93    * Values</em> phase.</p> 
   94   
   95    * <p>During the <em>Render Response</em> phase of the request
   96    * processing lifecycle, conversion for output occurs as for {@link
   97    * UIOutput}.</p>
   98   
   99    * <p>When the <code>validate()</code> method of this {@link UIInput}
  100    * detects that a value change has actually occurred, and that all
  101    * validations have been successfully passed, it will queue a {@link
  102    * ValueChangeEvent}.  Later on, the <code>broadcast()</code> method
  103    * will ensure that this event is broadcast to all interested listeners.
  104    * This event will be delivered by default in the <em>Process
  105    * Validators</em> phase, but can be delivered instead during <em>Apply
  106    * Request Values</em> if the <code>immediate</code> property is set to
  107    * <code>true</code>. <span class="changed_added_2_0">If the validation
  108    * fails, the implementation must call {@link
  109    * FacesContext#validationFailed}.</span></p>
  110   
  111    * <p>By default, the <code>rendererType</code> property must be set to
  112    * "<code>Text</code>".  This value can be changed by calling the
  113    * <code>setRendererType()</code> method.</p>
  114    */
  115   
  116   public class UIInput extends UIOutput implements EditableValueHolder {
  117   
  118       /* PENDING_2_1 (edburns,rogerk) this should be exposed as public constant */
  119       private static final String EMPTY_STRING_AS_NULL =
  120             "javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL";
  121   
  122       private static final String BEANS_VALIDATION_AVAILABLE =
  123             "javax.faces.private.BEANS_VALIDATION_AVAILABLE";
  124   
  125       // ------------------------------------------------------ Manifest Constants
  126   
  127   
  128       /**
  129        * <p>The standard component type for this component.</p>
  130        */
  131       public static final String COMPONENT_TYPE = "javax.faces.Input";
  132   
  133   
  134       /**
  135        * <p>The standard component family for this component.</p>
  136        */
  137       public static final String COMPONENT_FAMILY = "javax.faces.Input";
  138   
  139   
  140       /**
  141        * <p>The message identifier of the
  142        * {@link javax.faces.application.FacesMessage} to be created if
  143        * a conversion error occurs, and neither the page author nor
  144        * the {@link ConverterException} provides a message.</p>
  145        */
  146       public static final String CONVERSION_MESSAGE_ID =
  147            "javax.faces.component.UIInput.CONVERSION";
  148   
  149   
  150       /**
  151        * <p>The message identifier of the
  152        * {@link javax.faces.application.FacesMessage} to be created if
  153        * a required check fails.</p>
  154        */
  155       public static final String REQUIRED_MESSAGE_ID =
  156            "javax.faces.component.UIInput.REQUIRED";
  157   
  158       /**
  159        * <p>The message identifier of the
  160        * {@link javax.faces.application.FacesMessage} to be created if
  161        * a model update error occurs, and the thrown exception has
  162        * no message.</p>
  163        */
  164       public static final String UPDATE_MESSAGE_ID =
  165            "javax.faces.component.UIInput.UPDATE";
  166   
  167   
  168       /**
  169        * <p class="changed_added_2_0">The name of an application parameter
  170        * that indicates how empty values should be handled with respect to
  171        * validation.  See {@link #validateValue} for the allowable values
  172        * and specification of how they should be interpreted.</p>
  173        */
  174   
  175       public static final String VALIDATE_EMPTY_FIELDS_PARAM_NAME = 
  176   	"javax.faces.VALIDATE_EMPTY_FIELDS";
  177       
  178       private static final Validator[] EMPTY_VALIDATOR = new Validator[0];
  179   
  180       private Boolean emptyStringIsNull;
  181   
  182       private Boolean validateEmptyFields;
  183   
  184       enum PropertyKeys {
  185           /**
  186        * <p>The "localValueSet" state for this component.
  187        */
  188           localValueSet,
  189   
  190           /**
  191            * <p>If the input is required or not.</p>
  192            */
  193           required,
  194   
  195           /**
  196            * <p>Custom message to be displayed if input is required but non was submitted.</p>
  197            */
  198           requiredMessage,
  199   
  200           /**
  201            * <p>Custom message to be displayed when conversion fails.</p>
  202            */
  203           converterMessage,
  204   
  205           /**
  206            * <p>Custom message to be displayed when validation fails.</p>
  207            */
  208           validatorMessage,
  209   
  210           /**
  211            * <p>Flag indicating whether or not this component is valid.</p>
  212            */
  213           valid,
  214   
  215           /**
  216            * <p>Flag indicating when conversion/validation should occur.</p>
  217            */
  218           immediate,
  219   
  220       }
  221   
  222       // ------------------------------------------------------------ Constructors
  223   
  224   
  225       /**
  226        * <p>Create a new {@link UIInput} instance with default property
  227        * values.</p>
  228        */
  229       public UIInput() {
  230   
  231           super();
  232           setRendererType("javax.faces.Text");
  233   
  234       }
  235   
  236       // -------------------------------------------------------------- Properties
  237   
  238   
  239       public String getFamily() {
  240   
  241           return (COMPONENT_FAMILY);
  242   
  243       }
  244   
  245   
  246       /**
  247        * <p>The submittedValue value of this {@link UIInput} component.</p>
  248        */
  249       private Object submittedValue = null;
  250   
  251   
  252       /**
  253        * <p>Return the submittedValue value of this {@link UIInput} component.
  254        * This method should only be used by the <code>decode()</code> and
  255        * <code>validate()</code> method of this component, or
  256        * its corresponding {@link Renderer}.</p>
  257        */
  258       public Object getSubmittedValue() {
  259   
  260           return (this.submittedValue);
  261   
  262       }
  263   
  264   
  265       /**
  266        * <p>Set the submittedValue value of this {@link UIInput} component.
  267        * This method should only be used by the <code>decode()</code> and
  268        * <code>validate()</code> method of this component, or
  269        * its corresponding {@link Renderer}.</p>
  270        *
  271        * @param submittedValue The new submitted value
  272        */
  273       public void setSubmittedValue(Object submittedValue) {
  274   
  275           this.submittedValue = submittedValue;
  276   
  277       }
  278   
  279       public void setValue(Object value) {
  280           super.setValue(value);
  281           // Mark the local value as set.
  282           setLocalValueSet(true);
  283       }
  284   
  285       /**
  286        * <p>Convenience method to reset this component's value to the
  287        * un-initialized state.  This method does the following:</p>
  288        * <p/>
  289        * <p>Call {@link #setValue} passing <code>null</code>.</p>
  290        * <p/>
  291        * <p>Call {@link #setSubmittedValue} passing <code>null</code>.</p>
  292        * <p/>
  293        * <p>Call {@link #setLocalValueSet} passing <code>false</code>.</p>
  294        * <p/>
  295        * <p>Call {@link #setValid} passing <code>true</code>.</p>
  296        * <p/>
  297        * <p>Upon return from this call if the instance had a
  298        * <code>ValueBinding</code> associated with it for the "value"
  299        * property, this binding is evaluated when {@link
  300        * UIOutput#getValue} is called.  Otherwise, <code>null</code> is
  301        * returned from <code>getValue()</code>.</p>
  302        */
  303   
  304       public void resetValue() {
  305           this.setValue(null);
  306           this.setSubmittedValue(null);
  307           this.setLocalValueSet(false);
  308           this.setValid(true);
  309       }
  310   
  311   
  312       /**
  313        * Return the "local value set" state for this component.
  314        * Calls to <code>setValue()</code> automatically reset
  315        * this property to <code>true</code>.
  316        */
  317       public boolean isLocalValueSet() {
  318           return (Boolean) getStateHelper().eval(PropertyKeys.localValueSet, false);
  319       }
  320   
  321       /**
  322        * Sets the "local value set" state for this component.
  323        */
  324       public void setLocalValueSet(boolean localValueSet) {
  325           getStateHelper().put(PropertyKeys.localValueSet, localValueSet);
  326       }
  327   
  328   
  329       /**
  330        * <p>Return the "required field" state for this component.</p>
  331        */
  332       public boolean isRequired() {
  333   
  334           return (Boolean) getStateHelper().eval(PropertyKeys.required, false);
  335   
  336       }
  337   
  338   
  339       /**
  340        * <p>If there has been a call to {@link #setRequiredMessage} on this
  341        * instance, return the message.  Otherwise, call {@link #getValueExpression}
  342        * passing the key "requiredMessage", get the result of the expression, and return it.
  343        * Any {@link ELException}s thrown during the call to <code>getValue()</code>
  344        * must be wrapped in a {@link FacesException} and rethrown.
  345        */
  346   
  347       public String getRequiredMessage() {
  348   
  349           return (String) getStateHelper().eval(PropertyKeys.requiredMessage);
  350   
  351       }
  352   
  353       /**
  354        * <p>Override any {@link ValueExpression} set for the "requiredMessage"
  355        * with the literal argument provided to this method.  Subsequent calls
  356        * to {@link #getRequiredMessage} will return this value;</p>
  357        *
  358        * @param message the literal message value to be displayed in the event
  359        *                the user hasn't supplied a value and one is required.
  360        */
  361   
  362       public void setRequiredMessage(String message) {
  363   
  364           getStateHelper().put(PropertyKeys.requiredMessage,  message);
  365   
  366       }
  367   
  368   
  369       /**
  370        * <p>If there has been a call to {@link #setConverterMessage} on this
  371        * instance, return the message.  Otherwise, call {@link #getValueExpression}
  372        * passing the key "converterMessage", get the result of the expression, and return it.
  373        * Any {@link ELException}s thrown during the call to <code>getValue()</code>
  374        * must be wrapped in a {@link FacesException} and rethrown.
  375        */
  376   
  377       public String getConverterMessage() {
  378   
  379           return (String) getStateHelper().eval(PropertyKeys.converterMessage);
  380   
  381       }
  382   
  383       /**
  384        * <p>Override any {@link ValueExpression} set for the "converterMessage"
  385        * with the literal argument provided to this method.  Subsequent calls
  386        * to {@link #getConverterMessage} will return this value;</p>
  387        *
  388        * @param message the literal message value to be displayed in the event
  389        *                conversion fails.
  390        */
  391   
  392       public void setConverterMessage(String message) {
  393   
  394           getStateHelper().put(PropertyKeys.converterMessage, message);
  395   
  396       }
  397   
  398   
  399       /**
  400        * <p>If there has been a call to {@link #setValidatorMessage} on this
  401        * instance, return the message.  Otherwise, call {@link #getValueExpression}
  402        * passing the key "validatorMessage", get the result of the expression, and return it.
  403        * Any {@link ELException}s thrown during the call to <code>getValue()</code>
  404        * must be wrapped in a {@link FacesException} and rethrown.
  405        */
  406   
  407       public String getValidatorMessage() {
  408   
  409           return (String) getStateHelper().eval(PropertyKeys.validatorMessage);
  410   
  411       }
  412   
  413       /**
  414        * <p>Override any {@link ValueExpression} set for the "validatorMessage"
  415        * with the literal argument provided to this method.  Subsequent calls
  416        * to {@link #getValidatorMessage} will return this value;</p>
  417        *
  418        * @param message the literal message value to be displayed in the event
  419        *                validation fails.
  420        */
  421   
  422       public void setValidatorMessage(String message) {
  423   
  424           getStateHelper().put(PropertyKeys.validatorMessage, message);
  425   
  426       }
  427   
  428   
  429       public boolean isValid() {
  430   
  431           return (Boolean) getStateHelper().eval(PropertyKeys.valid, true);
  432   
  433       }
  434   
  435   
  436       public void setValid(boolean valid) {
  437   
  438           getStateHelper().put(PropertyKeys.valid, valid);
  439   
  440       }
  441   
  442   
  443       /**
  444        * <p>Set the "required field" state for this component.</p>
  445        *
  446        * @param required The new "required field" state
  447        */
  448       public void setRequired(boolean required) {
  449   
  450           getStateHelper().put(PropertyKeys.required, required);
  451   
  452       }
  453   
  454   
  455       public boolean isImmediate() {
  456   
  457           return (Boolean) getStateHelper().eval(PropertyKeys.immediate, false);
  458   
  459       }
  460   
  461   
  462       public void setImmediate(boolean immediate) {
  463   
  464           getStateHelper().put(PropertyKeys.immediate, immediate);
  465   
  466       }
  467   
  468   
  469       /**
  470        * <p>Return a <code>MethodBinding</code> pointing at a
  471        * method that will be called during <em>Process Validations</em>
  472        * phase of the request processing lifecycle, to validate the current
  473        * value of this component.</p>
  474        *
  475        * @deprecated {@link #getValidators} should be used instead.
  476        */
  477       public MethodBinding getValidator() {
  478           MethodBinding result = null;
  479   
  480           Validator[] curValidators = getValidators();
  481           // go through our lisetners list and find the one and only
  482           // MethodBindingValidator instance, if present.
  483           if (null != curValidators) {
  484               for (int i = 0; i < curValidators.length; i++) {
  485                   // We are guaranteed to have at most one instance of
  486                   // MethodBindingValidator in the curValidators list.
  487                   if (MethodBindingValidator.class ==
  488                        curValidators[i].getClass()) {
  489                       result = ((MethodBindingValidator) curValidators[i]).
  490                            getWrapped();
  491                       break;
  492                   }
  493               }
  494           }
  495           return result;
  496   
  497       }
  498   
  499   
  500       /**
  501        * <p>Set a <code>MethodBinding</code> pointing at a
  502        * method that will be called during <em>Process Validations</em>
  503        * phase of the request processing lifecycle, to validate the current
  504        * value of this component.</p>
  505        * <p/>
  506        * <p>Any method referenced by such an expression must be public, with
  507        * a return type of <code>void</code>, and accept parameters of type
  508        * {@link FacesContext}, {@link UIComponent}, and <code>Object</code>.</p>
  509        *
  510        * @param validatorBinding The new <code>MethodBinding</code> instance
  511        * @deprecated Use {@link #addValidator} instead, obtaining the
  512        *             argument {@link Validator} by creating an instance of {@link
  513        *             javax.faces.validator.MethodExpressionValidator}.
  514        */
  515       public void setValidator(MethodBinding validatorBinding) {
  516           Validator[] curValidators = getValidators();
  517           // see if we need to null-out, or replace an existing validator
  518           if (null != curValidators) {
  519               for (int i = 0; i < curValidators.length; i++) {
  520                   // if we want to remove the validatorBinding
  521                   if (null == validatorBinding) {
  522                       // We are guaranteed to have at most one instance of
  523                       // MethodBindingValidator in the curValidators
  524                       // list.
  525                       if (MethodBindingValidator.class ==
  526                            curValidators[i].getClass()) {
  527                           removeValidator(curValidators[i]);
  528                           return;
  529                       }
  530                   }
  531                   // if we want to replace the validatorBinding
  532                   else //noinspection ObjectEquality
  533                       if (validatorBinding == curValidators[i]) {
  534                       removeValidator(curValidators[i]);
  535                       break;
  536                   }
  537               }
  538           }
  539           addValidator(new MethodBindingValidator(validatorBinding));
  540   
  541       }
  542   
  543       public MethodBinding getValueChangeListener() {
  544           MethodBinding result = null;
  545   
  546           ValueChangeListener[] curListeners = getValueChangeListeners();
  547           // go through our lisetners list and find the one and only
  548           // MethodBindingValueChangeListener instance, if present.
  549           if (null != curListeners) {
  550               for (int i = 0; i < curListeners.length; i++) {
  551                   // We are guaranteed to have at most one instance of
  552                   // MethodBindingValueChangeListener in the curListeners list.
  553                   if (MethodBindingValueChangeListener.class ==
  554                        curListeners[i].getClass()) {
  555                       result = ((MethodBindingValueChangeListener) curListeners[i]).
  556                            getWrapped();
  557                       break;
  558                   }
  559               }
  560           }
  561           return result;
  562       }
  563   
  564   
  565       /**
  566        * {@inheritDoc}
  567        *
  568        * @deprecated Use {@link #addValueChangeListener} instead, obtaining the
  569        *             argument {@link ValueChangeListener} by creating an instance of {@link
  570        *             javax.faces.event.MethodExpressionValueChangeListener}.
  571        */
  572       public void setValueChangeListener(MethodBinding valueChangeListener) {
  573   
  574           ValueChangeListener[] curListeners = getValueChangeListeners();
  575           // see if we need to null-out, or replace an existing listener
  576           if (null != curListeners) {
  577               for (int i = 0; i < curListeners.length; i++) {
  578                   // if we want to remove the valueChangeListener
  579                   if (null == valueChangeListener) {
  580                       // We are guaranteed to have at most one instance of
  581                       // MethodBindingValueChangeListener in the curListeners
  582                       // list.
  583                       if (MethodBindingValueChangeListener.class ==
  584                            curListeners[i].getClass()) {
  585                           removeFacesListener(curListeners[i]);
  586                           return;
  587                       }
  588                   }
  589                   // if we want to replace the valueChangeListener
  590                   else //noinspection ObjectEquality
  591                       if (valueChangeListener == curListeners[i]) {
  592                       removeFacesListener(curListeners[i]);
  593                       break;
  594                   }
  595               }
  596           }
  597           addValueChangeListener(new MethodBindingValueChangeListener(valueChangeListener));
  598       }
  599   
  600       // ----------------------------------------------------- UIComponent Methods
  601   
  602   
  603       /**
  604        * <p>
  605        * In addition to the actions taken in {@link UIOutput}
  606        * when {@link PartialStateHolder#markInitialState()} is called,
  607        * check if any of the installed {@link Validator}s are PartialStateHolders and
  608        * if so, call {@link javax.faces.component.PartialStateHolder#markInitialState()}
  609        * as appropriate.
  610        * </p>
  611        */
  612       @Override
  613       public void markInitialState() {
  614   
  615           super.markInitialState();
  616           if (validators != null) {
  617               validators.markInitialState();
  618           }
  619   
  620       }
  621   
  622   
  623       @Override
  624       public void clearInitialState() {
  625   
  626           if (initialStateMarked()) {
  627               super.clearInitialState();
  628               if (validators != null) {
  629                   validators.clearInitialState();
  630               }
  631           }
  632   
  633       }
  634   
  635   
  636       /**
  637        * <p>Specialized decode behavior on top of that provided by the
  638        * superclass.  In addition to the standard
  639        * <code>processDecodes</code> behavior inherited from {@link
  640        * UIComponentBase}, calls <code>validate()</code> if the the
  641        * <code>immediate</code> property is true; if the component is
  642        * invalid afterwards or a <code>RuntimeException</code> is thrown,
  643        * calls {@link FacesContext#renderResponse}.  </p>
  644        *
  645        * @throws NullPointerException {@inheritDoc}
  646        */
  647       public void processDecodes(FacesContext context) {
  648   
  649           if (context == null) {
  650               throw new NullPointerException();
  651           }
  652   
  653           // Skip processing if our rendered flag is false
  654           if (!isRendered()) {
  655               return;
  656           }
  657   
  658           super.processDecodes(context);
  659   
  660           if (isImmediate()) {
  661               executeValidate(context);
  662           }
  663       }
  664   
  665       /**
  666        * <p>In addition to the standard <code>processValidators</code> behavior
  667        * inherited from {@link UIComponentBase}, calls <code>validate()</code>
  668        * if the <code>immediate</code> property is false (which is the
  669        * default);  if the component is invalid afterwards, calls
  670        * {@link FacesContext#renderResponse}.
  671        * If a <code>RuntimeException</code> is thrown during
  672        * validation processing, calls {@link FacesContext#renderResponse}
  673        * and re-throw the exception.
  674        * </p>
  675        *
  676        * @throws NullPointerException {@inheritDoc}
  677        */
  678       public void processValidators(FacesContext context) {
  679   
  680           if (context == null) {
  681               throw new NullPointerException();
  682           }
  683   
  684           // Skip processing if our rendered flag is false
  685           if (!isRendered()) {
  686               return;
  687           }
  688   
  689           super.processValidators(context);
  690           if (!isImmediate()) {
  691               executeValidate(context);
  692           }
  693       }
  694   
  695       /**
  696        * <p>In addition to the standard <code>processUpdates</code> behavior
  697        * inherited from {@link UIComponentBase}, calls
  698        * <code>updateModel()</code>.
  699        * If the component is invalid afterwards, calls
  700        * {@link FacesContext#renderResponse}.
  701        * If a <code>RuntimeException</code> is thrown during
  702        * update processing, calls {@link FacesContext#renderResponse}
  703        * and re-throw the exception.
  704        * </p>
  705        *
  706        * @throws NullPointerException {@inheritDoc}
  707        */
  708       public void processUpdates(FacesContext context) {
  709   
  710           if (context == null) {
  711               throw new NullPointerException();
  712           }
  713   
  714           // Skip processing if our rendered flag is false
  715           if (!isRendered()) {
  716               return;
  717           }
  718   
  719           super.processUpdates(context);
  720   
  721           try {
  722               updateModel(context);
  723           } catch (RuntimeException e) {
  724               context.renderResponse();
  725               throw e;
  726           }
  727   
  728           if (!isValid()) {
  729               context.renderResponse();
  730           }
  731       }
  732   
  733       /**
  734        * @throws NullPointerException {@inheritDoc}
  735        */
  736       public void decode(FacesContext context) {
  737   
  738           if (context == null) {
  739               throw new NullPointerException();
  740           }
  741   
  742           // Force validity back to "true"
  743           setValid(true);
  744           super.decode(context);
  745       }
  746   
  747       /**
  748        * <p><span class="changed_modified_2_0">Perform</span>
  749        * the following algorithm to update the model data
  750        * associated with this {@link UIInput}, if any, as appropriate.</p>
  751        * <ul>
  752        * <li>If the <code>valid</code> property of this component is
  753        * <code>false</code>, take no further action.</li>
  754        * <li>If the <code>localValueSet</code> property of this component is
  755        * <code>false</code>, take no further action.</li>
  756        * <li>If no {@link ValueExpression} for <code>value</code> exists,
  757        * take no further action.</li>
  758        * <li>Call <code>setValue()</code> method of the {@link ValueExpression}
  759        * to update the value that the {@link ValueExpression} points at.</li>
  760        * <li>If the <code>setValue()</code> method returns successfully:
  761        * <ul>
  762        * <li>Clear the local value of this {@link UIInput}.</li>
  763        * <li>Set the <code>localValueSet</code> property of this
  764        * {@link UIInput} to false.</li>
  765        * </ul></li>
  766        * <li>If the <code>setValue()</code> method throws an Exception:
  767        * <ul>
  768        * <li class="changed_modified_2_0">Enqueue an error message.  Create a 
  769        * {@link FacesMessage} with the id {@link #UPDATE_MESSAGE_ID}.  Create a
  770        * {@link UpdateModelException}, passing the <code>FacesMessage</code> and 
  771        * the caught exception to the constructor.  Create an 
  772        * {@link ExceptionQueuedEventContext}, passing the <code>FacesContext</code>, 
  773        * the <code>UpdateModelException</code>, this component instance, and
  774        * {@link PhaseId#UPDATE_MODEL_VALUES} to its constructor.  Call 
  775        * {@link FacesContext#getExceptionHandler} and then call 
  776        * {@link ExceptionHandler#processEvent}, passing the 
  777        * <code>ExceptionQueuedEventContext</code>.
  778        * </li>
  779        * <li>Set the <code>valid</code> property of this {@link UIInput}
  780        * to <code>false</code>.</li>
  781        * </ul></li>
  782        * The exception must not be re-thrown.  This enables tree traversal
  783        * to continue for this lifecycle phase, as in all the other lifecycle
  784        * phases. 
  785        * </ul>
  786        *
  787        * @param context {@link FacesContext} for the request we are processing
  788        * @throws NullPointerException if <code>context</code>
  789        *                              is <code>null</code>
  790        */
  791       public void updateModel(FacesContext context) {
  792   
  793           if (context == null) {
  794               throw new NullPointerException();
  795           }
  796   
  797           if (!isValid() || !isLocalValueSet()) {
  798               return;
  799           }
  800           ValueExpression ve = getValueExpression("value");
  801           if (ve != null) {
  802               Throwable caught = null;
  803               FacesMessage message = null;
  804               try {
  805                   ve.setValue(context.getELContext(), getLocalValue());
  806                   setValue(null);
  807                   setLocalValueSet(false);
  808               } catch (ELException e) {
  809                   caught = e;
  810                   String messageStr = e.getMessage();
  811                   Throwable result = e.getCause();
  812                   while (null != result &&
  813                        result.getClass().isAssignableFrom(ELException.class)) {
  814                       messageStr = result.getMessage();
  815                       result = result.getCause();
  816                   }
  817                   if (null == messageStr) {
  818                       message =
  819                            MessageFactory.getMessage(context, UPDATE_MESSAGE_ID,
  820                                 MessageFactory.getLabel(
  821                                      context, this));
  822                   } else {
  823                       message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
  824                                                  messageStr,
  825                                                  messageStr);
  826                   }
  827                   setValid(false);
  828               } catch (Exception e) {
  829                   caught = e;
  830                   message =
  831                        MessageFactory.getMessage(context, UPDATE_MESSAGE_ID,
  832                             MessageFactory.getLabel(
  833                                  context, this));
  834                   setValid(false);
  835               }
  836               if (caught != null) {
  837                   assert(message != null);
  838                   @SuppressWarnings({"ThrowableInstanceNeverThrown"})
  839                   UpdateModelException toQueue =
  840                         new UpdateModelException(message, caught);
  841                   ExceptionQueuedEventContext eventContext =
  842                         new ExceptionQueuedEventContext(context,
  843                                                   toQueue,
  844                                                   this,
  845                                                   PhaseId.UPDATE_MODEL_VALUES);
  846                   context.getApplication().publishEvent(context,
  847                                                         ExceptionQueuedEvent.class,
  848                                                         eventContext);
  849                   
  850               }
  851               
  852           }
  853       }
  854       
  855       // ------------------------------------------------------ Validation Methods
  856   
  857   
  858       /**
  859        * <p><span class="changed_modified_2_0">Perform</span> the
  860        * following algorithm to validate the local value of this {@link
  861        * UIInput}.</p>
  862   
  863        * <ul>
  864   
  865        * <li>Retrieve the submitted value with {@link #getSubmittedValue}.
  866        * If this returns <code>null</code>, exit without further
  867        * processing.  (This indicates that no value was submitted for this
  868        * component.)</li>
  869   
  870        * <p/>
  871   
  872        * <li><span class="changed_modified_2_0">If the
  873        * <code>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</code>
  874        * context parameter value is <code>true</code> (ignoring case), and
  875        * <code>getSubmittedValue()</code> returns a zero-length
  876        * <code>String</code> call <code>{@link #setSubmittedValue}</code>,
  877        * passing <code>null</code> as the argument and continue processing
  878        * using <code>null</code> as the current submitted
  879        * value.</code></span></li>
  880   
  881        * <p/>
  882   
  883        * <li> Convert the submitted value into a "local value" of the
  884        * appropriate data type by calling {@link #getConvertedValue}.</li>
  885        * <p/>
  886        * <li>Validate the property by calling {@link #validateValue}.</li>
  887        * <p/>
  888        * <li>If the <code>valid</code> property of this component is still
  889        * <code>true</code>, retrieve the previous value of the component
  890        * (with <code>getValue()</code>), store the new local value using
  891        * <code>setValue()</code>, and reset the submitted value to
  892        * null.  If the local value is different from
  893        * the previous value of this component, fire a
  894        * {@link ValueChangeEvent} to be broadcast to all interested
  895        * listeners.</li>
  896        * </ul>
  897        * <p/>
  898        * <p>Application components implementing {@link UIInput} that wish to
  899        * perform validation with logic embedded in the component should perform
  900        * their own correctness checks, and then call the
  901        * <code>super.validate()</code> method to perform the standard
  902        * processing described above.</p>
  903        *
  904        * @param context The {@link FacesContext} for the current request
  905        * @throws NullPointerException if <code>context</code>
  906        *                              is null
  907        */
  908       public void validate(FacesContext context) {
  909   
  910           if (context == null) {
  911               throw new NullPointerException();
  912           }
  913   
  914           // Submitted value == null means "the component was not submitted
  915           // at all".  
  916           Object submittedValue = getSubmittedValue();
  917           if (submittedValue == null) {
  918               return;
  919           }
  920   
  921           // If non-null, an instanceof String, and we're configured to treat
  922           // zero-length Strings as null:
  923           //   call setSubmittedValue(null)
  924           if ((considerEmptyStringNull(context)
  925                && submittedValue instanceof String 
  926                && ((String) submittedValue).length() == 0)) {
  927               setSubmittedValue(null);
  928               submittedValue = null;
  929           }
  930   
  931           Object newValue = null;
  932   
  933           try {
  934               newValue = getConvertedValue(context, submittedValue);
  935           }
  936           catch (ConverterException ce) {
  937               addConversionErrorMessage(context, ce);
  938               setValid(false);
  939           }
  940   
  941           validateValue(context, newValue);
  942   
  943           // If our value is valid, store the new value, erase the
  944           // "submitted" value, and emit a ValueChangeEvent if appropriate
  945           if (isValid()) {
  946               Object previous = getValue();
  947               setValue(newValue);
  948               setSubmittedValue(null);
  949               if (compareValues(previous, newValue)) {
  950                   queueEvent(new ValueChangeEvent(this, previous, newValue));
  951               }
  952           }
  953   
  954       }
  955   
  956       /**
  957        * <p>Convert the submitted value into a "local value" of the
  958        * appropriate data type, if necessary.  Employ the following
  959        * algorithm to do so:</p>
  960        * <ul>
  961        * <li>If a <code>Renderer</code> is present, call
  962        * <code>getConvertedValue()</code> to convert the submitted
  963        * value.</li>
  964        * <li>If no <code>Renderer</code> is present, and the submitted
  965        * value is a String, locate a {@link Converter} as follows:
  966        * <ul>
  967        * <li>If <code>getConverter()</code> returns a non-null {@link Converter},
  968        * use that instance.</li>
  969        * <li>Otherwise, if a value binding for <code>value</code> exists,
  970        * call <code>getType()</code> on it.
  971        * <ul>
  972        * <li>If this call returns <code>null</code>, assume the output
  973        * type is <code>String</code> and perform no conversion.</li>
  974        * <li>Otherwise, call
  975        * <code>Application.createConverter(Class)</code>
  976        * to locate any registered {@link Converter} capable of
  977        * converting data values of the specified type.</li>
  978        * </ul>
  979        * </li>
  980        * </ul>
  981        * <li>If a {@link Converter} instance was located, call its
  982        * <code>getAsObject()</code> method to perform the conversion.
  983        * If conversion fails:
  984        * <ul>
  985        * <li>Enqueue an appropriate error message by calling the
  986        * <code>addMessage()</code> method on the
  987        * <code>FacesContext</code>.</li>
  988        * <li>Set the <code>valid</code> property
  989        * on this component to <code>false</code> </li>
  990        * </ul></li>
  991        * <li>Otherwise, use the submitted value without any conversion</li>
  992        * </ul>
  993        * </li>
  994        * <p/>
  995        * </p>
  996        * <p/>
  997        * <p>This method can be overridden by subclasses for more specific
  998        * behavior.</p>
  999        */
 1000   
 1001   
 1002       protected Object getConvertedValue(FacesContext context,
 1003                                          Object newSubmittedValue) throws ConverterException {
 1004           Renderer renderer = getRenderer(context);
 1005           Object newValue;
 1006   
 1007           if (renderer != null) {
 1008               newValue = renderer.getConvertedValue(context, this,
 1009                    newSubmittedValue);
 1010           } else if (newSubmittedValue instanceof String) {
 1011               // If there's no Renderer, and we've got a String,
 1012               // run it through the Converter (if any)
 1013               Converter converter = getConverterWithType(context);
 1014               if (converter != null) {
 1015                   newValue = converter.getAsObject(context, this,
 1016                        (String) newSubmittedValue);
 1017               } else {
 1018                   newValue = newSubmittedValue;
 1019               }
 1020           } else {
 1021               newValue = newSubmittedValue;
 1022           }
 1023           return newValue;
 1024       }
 1025   
 1026       /**
 1027        * <p><span class="changed_modified_2_0">Set</span> the "valid"
 1028        * property according to the below algorithm.</p>
 1029   
 1030        * <ul>
 1031   
 1032        * <li>
 1033   
 1034        * <p>If the <code>valid</code> property on this component is
 1035        * still <code>true</code>, and the <code>required</code> property
 1036        * is also <code>true</code>, ensure that the local value is not
 1037        * empty (where "empty" is defined as <code>null</code> or a
 1038        * zero-length String).  If the local value is empty:</p>
 1039   
 1040        * <ul>
 1041   
 1042        * <li><p>Enqueue an appropriate error message by calling the
 1043        * <code>addMessage()</code> method on the <code>FacesContext</code>
 1044        * instance for the current request.  If the {@link
 1045        * #getRequiredMessage} returns non-<code>null</code>, use the value
 1046        * as the <code>summary</code> and <code>detail</code> in the {@link
 1047        * FacesMessage} that is enqueued on the <code>FacesContext</code>,
 1048        * otherwise use the message for the {@link #REQUIRED_MESSAGE_ID}.
 1049        * </li> <li>Set the <code>valid</code> property on this component
 1050        * to <code>false</code>.</p></li> 
 1051   
 1052        * <li><p class="changed_modified_2_0">If calling {@link
 1053        * ValidatorException#getFacesMessages} returns
 1054        * non-<code>null</code>, each message should be added to the
 1055        * <code>FacesContext</code>.  Otherwise the single message returned
 1056        * from {@link ValidatorException#getFacesMessage} should be
 1057        * added.</p></li>
 1058        *
 1059        * </ul>
 1060   
 1061        * </li>
 1062        *
 1063        *
 1064        * <li class="changed_added_2_0"><p>Otherwise, if the
 1065        * <code>valid</code> property on this component is still
 1066        * <code>true</code>, take the following action to determine if
 1067        * validation of this component should proceed.</p>
 1068   
 1069        * <ul>
 1070        *
 1071        * <li><p>If the value is not empty, validation should proceed.</p></li>
 1072   
 1073        * <li><p>If the value is empty, but the system has been directed to
 1074        * validate empty fields, validation should proceed.  The
 1075        * implementation must obtain the init parameter <code>Map</code>
 1076        * from the <code>ExternalContext</code> and inspect the value for
 1077        * the key given by the value of the symbolic constant {@link
 1078        * #VALIDATE_EMPTY_FIELDS_PARAM_NAME}.  If there is no value under
 1079        * that key, use the same key and look in the application map from
 1080        * the <code>ExternalContext</code>.  If the value is
 1081        * <code>null</code> or equal to the string
 1082        * &#8220;<code>auto</code>&#8221; (without the quotes) take
 1083        * appropriate action to determine if Bean Validation is present in
 1084        * the runtime environment.  If not, validation should not proceed.
 1085        * If so, validation should proceed.  If the value is equal
 1086        * (ignoring case) to &#8220;<code>true</code>&#8221; (without the
 1087        * quotes) validation should proceed.  Otherwise, validation should
 1088        * not proceed.</p></li>
 1089   
 1090        * <p>If the above determination indicates that validation should
 1091        * proceed, call the <code>validate()</code> method of each {@link
 1092        * Validator} registered for this {@link UIInput}, followed by the
 1093        * method pointed at by the <code>validatorBinding</code> property
 1094        * (if any).  If any of these validators or the method throws a
 1095        * {@link ValidatorException}, catch the exception, add its message
 1096        * (if any) to the {@link FacesContext}, and set the
 1097        * <code>valid</code> property of this component to false.</li>
 1098   
 1099        * </ul>
 1100        */
 1101   
 1102       protected void validateValue(FacesContext context, Object newValue) {
 1103           // If our value is valid, enforce the required property if present
 1104           if (isValid() && isRequired() && isEmpty(newValue)) {
 1105               String requiredMessageStr = getRequiredMessage();
 1106               FacesMessage message;
 1107               if (null != requiredMessageStr) {
 1108                   message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
 1109                                              requiredMessageStr,
 1110                                              requiredMessageStr);
 1111               } else {
 1112                   message =
 1113                        MessageFactory.getMessage(context, REQUIRED_MESSAGE_ID,
 1114                             MessageFactory.getLabel(
 1115                                  context, this));
 1116               }
 1117               context.addMessage(getClientId(context), message);
 1118               setValid(false);
 1119           }
 1120   
 1121           // If our value is valid and not empty or empty w/ validate empty fields enabled, call all validators
 1122           if (isValid() && (!isEmpty(newValue) || validateEmptyFields(context))) {
 1123               if (validators != null) {
 1124                   Validator[] validators = this.validators.asArray(Validator.class);
 1125                   for (Validator validator : validators) {
 1126                       try {
 1127                           validator.validate(context, this, newValue);
 1128                       }
 1129                       catch (ValidatorException ve) {
 1130                           // If the validator throws an exception, we're
 1131                           // invalid, and we need to add a message
 1132                           setValid(false);
 1133                           FacesMessage message;
 1134                           String validatorMessageString = getValidatorMessage();
 1135   
 1136                           if (null != validatorMessageString) {
 1137                               message =
 1138                                     new FacesMessage(FacesMessage.SEVERITY_ERROR,
 1139                                                      validatorMessageString,
 1140                                                      validatorMessageString);
 1141                               message.setSeverity(FacesMessage.SEVERITY_ERROR);
 1142                           } else {
 1143                               Collection<FacesMessage> messages = ve.getFacesMessages();
 1144                               if (null != messages) {
 1145                                   message = null;
 1146                                   String cid = getClientId(context);
 1147                                   for (FacesMessage m : messages) {
 1148                                       context.addMessage(cid, m);
 1149                                   }
 1150                               } else {
 1151                                   message = ve.getFacesMessage();
 1152                               }
 1153                           }
 1154                           if (message != null) {
 1155                               context.addMessage(getClientId(context), message);
 1156                           }
 1157                       }
 1158                   }
 1159               }
 1160           }
 1161       }
 1162   
 1163   
 1164       /**
 1165        * <p>Return <code>true</code> if the new value is different from the
 1166        * previous value.</p>
 1167        *
 1168        * @param previous old value of this component (if any)
 1169        * @param value    new value of this component (if any)
 1170        */
 1171       protected boolean compareValues(Object previous, Object value) {
 1172   
 1173           if (previous == null) {
 1174               return (value != null);
 1175           } else if (value == null) {
 1176               return (true);
 1177           } else {
 1178               return (!(previous.equals(value)));
 1179           }
 1180   
 1181       }
 1182   
 1183   
 1184       /**
 1185        * Executes validation logic.
 1186        */
 1187       private void executeValidate(FacesContext context) {
 1188           try {
 1189               validate(context);
 1190           } catch (RuntimeException e) {
 1191               context.renderResponse();
 1192               throw e;
 1193           }
 1194   
 1195           if (!isValid()) {
 1196               context.validationFailed();
 1197               context.renderResponse();
 1198           }
 1199       }
 1200   
 1201       public static boolean isEmpty(Object value) {
 1202   
 1203           if (value == null) {
 1204               return (true);
 1205           } else if ((value instanceof String) &&
 1206                (((String) value).length() < 1)) {
 1207               return (true);
 1208           } else if (value.getClass().isArray()) {
 1209               if (0 == java.lang.reflect.Array.getLength(value)) {
 1210                   return (true);
 1211               }
 1212           } else if (value instanceof List) {
 1213               if (((List) value).isEmpty()) {
 1214                   return (true);
 1215               }
 1216           }
 1217           return (false);
 1218       }
 1219   
 1220   
 1221       /**
 1222        * <p>The set of {@link Validator}s associated with this
 1223        * <code>UIComponent</code>.</p>
 1224        */
 1225       AttachedObjectListHolder<Validator> validators;
 1226   
 1227   
 1228       /**
 1229        * <p>Add a {@link Validator} instance to the set associated with
 1230        * this {@link UIInput}.</p>
 1231        *
 1232        * @param validator The {@link Validator} to add
 1233        * @throws NullPointerException if <code>validator</code>
 1234        *                              is null
 1235        */
 1236       public void addValidator(Validator validator) {
 1237   
 1238           if (validator == null) {
 1239               throw new NullPointerException();
 1240           }
 1241   
 1242           if (validators == null) {
 1243               validators = new AttachedObjectListHolder<Validator>();
 1244           }
 1245           validators.add(validator);
 1246   
 1247       }
 1248       
 1249   
 1250       /**
 1251        * <p>Return the set of registered {@link Validator}s for this
 1252        * {@link UIInput} instance.  If there are no registered validators,
 1253        * a zero-length array is returned.</p>
 1254        */
 1255       public Validator[] getValidators() {
 1256   
 1257           return ((validators != null) ? validators.asArray(Validator.class) : EMPTY_VALIDATOR);
 1258   
 1259       }
 1260   
 1261   
 1262       /**
 1263        * <p>Remove a {@link Validator} instance from the set associated with
 1264        * this {@link UIInput}, if it was previously associated.
 1265        * Otherwise, do nothing.</p>
 1266        *
 1267        * @param validator The {@link Validator} to remove
 1268        */
 1269       public void removeValidator(Validator validator) {
 1270   
 1271           if (validator == null) {
 1272               return;
 1273           }
 1274   
 1275           if (validators != null) {
 1276               validators.remove(validator);
 1277           }
 1278   
 1279       }
 1280   
 1281       // ------------------------------------------------ Event Processing Methods
 1282   
 1283   
 1284       /**
 1285        * <p>Add a new {@link ValueChangeListener} to the set of listeners
 1286        * interested in being notified when {@link ValueChangeEvent}s occur.</p>
 1287        *
 1288        * @param listener The {@link ValueChangeListener} to be added
 1289        * @throws NullPointerException if <code>listener</code>
 1290        *                              is <code>null</code>
 1291        */
 1292       public void addValueChangeListener(ValueChangeListener listener) {
 1293   
 1294           addFacesListener(listener);
 1295   
 1296       }
 1297   
 1298   
 1299       /**
 1300        * <p>Return the set of registered {@link ValueChangeListener}s for this
 1301        * {@link UIInput} instance.  If there are no registered listeners,
 1302        * a zero-length array is returned.</p>
 1303        */
 1304       public ValueChangeListener[] getValueChangeListeners() {
 1305   
 1306           return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class);
 1307       }
 1308   
 1309   
 1310       /**
 1311        * <p>Remove an existing {@link ValueChangeListener} (if any) from the
 1312        * set of listeners interested in being notified when
 1313        * {@link ValueChangeEvent}s occur.</p>
 1314        *
 1315        * @param listener The {@link ValueChangeListener} to be removed
 1316        * @throws NullPointerException if <code>listener</code>
 1317        *                              is <code>null</code>
 1318        */
 1319       public void removeValueChangeListener(ValueChangeListener listener) {
 1320   
 1321           removeFacesListener(listener);
 1322   
 1323       }
 1324   
 1325       // ----------------------------------------------------- StateHolder Methods
 1326   
 1327   
 1328   
 1329       private Object[] values;
 1330   
 1331       public Object saveState(FacesContext context) {
 1332   
 1333           if (context == null) {
 1334               throw new NullPointerException();
 1335           }
 1336           if (values == null) {
 1337               values = new Object[4];
 1338           }
 1339   
 1340           values[0] = super.saveState(context);
 1341           values[1] = emptyStringIsNull;
 1342           values[2] = validateEmptyFields;
 1343           values[3] = ((validators != null) ? validators.saveState(context) : null);
 1344           return (values);
 1345   
 1346       }
 1347   
 1348   
 1349       public void restoreState(FacesContext context, Object state) {
 1350   
 1351           if (context == null) {
 1352               throw new NullPointerException();
 1353           }
 1354   
 1355           if (state == null) {
 1356               return;
 1357           }
 1358           values = (Object[]) state;
 1359           super.restoreState(context, values[0]);
 1360           emptyStringIsNull = (Boolean) values[1];
 1361           validateEmptyFields = (Boolean) values[2];
 1362           if (values[3] != null) {
 1363               if (validators == null) {
 1364                   validators = new AttachedObjectListHolder<Validator>();
 1365               }
 1366               validators.restoreState(context, values[3]);
 1367           }
 1368   
 1369       }
 1370   
 1371       private Converter getConverterWithType(FacesContext context) {
 1372           Converter converter = getConverter();
 1373           if (converter != null) {
 1374               return converter;
 1375           }
 1376   
 1377           ValueExpression valueExpression = getValueExpression("value");
 1378           if (valueExpression == null) {
 1379               return null;
 1380           }
 1381   
 1382           Class converterType;
 1383           try {
 1384               converterType = valueExpression.getType(context.getELContext());
 1385           }
 1386           catch (ELException e) {
 1387               throw new FacesException(e);
 1388           }
 1389   
 1390           // if converterType is null, String, or Object, assume
 1391           // no conversion is needed
 1392           if (converterType == null ||
 1393                converterType == String.class ||
 1394                converterType == Object.class) {
 1395               return null;
 1396           }
 1397   
 1398           // if getType returns a type for which we support a default
 1399           // conversion, acquire an appropriate converter instance.
 1400           try {
 1401               Application application = context.getApplication();
 1402               return application.createConverter(converterType);
 1403           } catch (Exception e) {
 1404               return (null);
 1405           }
 1406       }
 1407   
 1408       private void addConversionErrorMessage(FacesContext context,
 1409                                              ConverterException ce) {
 1410           FacesMessage message;
 1411           String converterMessageString = getConverterMessage();
 1412           if (null != converterMessageString) {
 1413               message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
 1414                                          converterMessageString,
 1415                                          converterMessageString);
 1416           } else {
 1417               message = ce.getFacesMessage();
 1418               if (message == null) {
 1419                   message = MessageFactory.getMessage(context,
 1420                        CONVERSION_MESSAGE_ID);                
 1421                   if (message.getDetail() == null) {
 1422                       message.setDetail(ce.getMessage());
 1423                   }
 1424               }
 1425           }
 1426   
 1427           context.addMessage(getClientId(context), message);
 1428       }
 1429   
 1430   
 1431       private boolean considerEmptyStringNull(FacesContext ctx) {
 1432   
 1433           if (emptyStringIsNull == null) {
 1434               String val = ctx.getExternalContext().getInitParameter(EMPTY_STRING_AS_NULL);
 1435               emptyStringIsNull = Boolean.valueOf(val);
 1436           }
 1437   
 1438           return emptyStringIsNull;
 1439           
 1440       }
 1441   
 1442       private boolean validateEmptyFields(FacesContext ctx) {
 1443   
 1444           if (validateEmptyFields == null) {
 1445               ExternalContext extCtx = ctx.getExternalContext();
 1446               String val = extCtx.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
 1447   
 1448               if (null == val) {
 1449                   val = (String) extCtx.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
 1450               }
 1451               if (val == null || "auto".equals(val)) {
 1452                   validateEmptyFields = isBeansValidationAvailable(ctx);
 1453               } else {
 1454                   validateEmptyFields = Boolean.valueOf(val);
 1455               }
 1456           }
 1457   
 1458           return validateEmptyFields;
 1459   
 1460       }
 1461       
 1462       private boolean isBeansValidationAvailable(FacesContext context) {
 1463           boolean result = false;
 1464   
 1465           Map<String,Object> appMap = context.getExternalContext().getApplicationMap();
 1466           
 1467           if (appMap.containsKey(BEANS_VALIDATION_AVAILABLE)) {
 1468               result = (Boolean) appMap.get(BEANS_VALIDATION_AVAILABLE);
 1469           } else {
 1470               try {
 1471                   new BeanValidator();
 1472                   appMap.put(BEANS_VALIDATION_AVAILABLE, result = true);
 1473               } catch (Throwable t) {
 1474                   appMap.put(BEANS_VALIDATION_AVAILABLE, Boolean.FALSE);
 1475               }
 1476           }
 1477   
 1478           return result;
 1479       }
 1480   
 1481   }

Home » Mojarra-2.0.1 » javax » faces » component » [javadoc | source]