All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.faces.component.UIInput Maven / Gradle / Ivy

Go to download

This is the master POM file for Sun's Implementation of the JSF 1.2 Specification.

There is a newer version: 2.1
Show newest version
/*
 * $Id: UIInput.java,v 1.93.4.2 2007/11/05 21:48:57 rlubke Exp $
 */

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package javax.faces.component;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.el.ELException;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.el.MethodBinding;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
import javax.faces.render.Renderer;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

/**
 * 

UIInput is a {@link UIComponent} that represents * a component that both displays output to the user (like * {@link UIOutput} components do) and processes request parameters on the * subsequent request that need to be decoded. There are no restrictions * on the data type of the local value, or the object referenced by the * value binding expression (if any); however, individual * {@link javax.faces.render.Renderer}s will generally impose restrictions * on the type of data they know how to display.

*

*

During the Apply Request Values phase of the request * processing lifecycle, the decoded value of this component, usually * but not necessarily a String, must be stored - but not yet converted - * using setSubmittedValue(). If the component wishes * to indicate that no particular value was submitted, it can either * do nothing, or set the submitted value to null.

*

*

By default, during the Process Validators phase of the * request processing lifecycle, the submitted value will be converted * to a typesafe object, and, if validation succeeds, stored as a * local value using setValue(). However, if the * immediate property is set to true, this * processing will occur instead at the end of the * Apply Request Values phase. *

*

During the Render Response phase of the request processing * lifecycle, conversion for output occurs as for {@link UIOutput}.

*

*

When the validate() method of this {@link UIInput} * detects that a value change has actually occurred, and that all validations * have been successfully passed, it will queue a * {@link ValueChangeEvent}. Later on, the broadcast() * method will ensure that this event is broadcast to all interested * listeners. This event will be delivered by default in the * Process Validators phase, but can be delivered instead * during Apply Request Values if the immediate * property is set to true.

*

*

By default, the rendererType property must be set to * "Text". This value can be changed by calling the * setRendererType() method.

*/ public class UIInput extends UIOutput implements EditableValueHolder { // ------------------------------------------------------ Manifest Constants /** *

The standard component type for this component.

*/ public static final String COMPONENT_TYPE = "javax.faces.Input"; /** *

The standard component family for this component.

*/ public static final String COMPONENT_FAMILY = "javax.faces.Input"; /** *

The message identifier of the * {@link javax.faces.application.FacesMessage} to be created if * a conversion error occurs, and neither the page author nor * the {@link ConverterException} provides a message.

*/ public static final String CONVERSION_MESSAGE_ID = "javax.faces.component.UIInput.CONVERSION"; /** *

The message identifier of the * {@link javax.faces.application.FacesMessage} to be created if * a required check fails.

*/ public static final String REQUIRED_MESSAGE_ID = "javax.faces.component.UIInput.REQUIRED"; /** *

The message identifier of the * {@link javax.faces.application.FacesMessage} to be created if * a model update error occurs, and the thrown exception has * no message.

*/ public static final String UPDATE_MESSAGE_ID = "javax.faces.component.UIInput.UPDATE"; private static final Validator[] EMPTY_VALIDATOR = new Validator[0]; /** * The Logger for this class. */ private static final Logger LOGGER = Logger.getLogger("javax.faces.component", "javax.faces.LogStrings"); // ------------------------------------------------------------ Constructors /** *

Create a new {@link UIInput} instance with default property * values.

*/ public UIInput() { super(); setRendererType("javax.faces.Text"); } // -------------------------------------------------------------- Properties public String getFamily() { return (COMPONENT_FAMILY); } /** *

The submittedValue value of this {@link UIInput} component.

*/ private Object submittedValue = null; /** *

Return the submittedValue value of this {@link UIInput} component. * This method should only be used by the decode() and * validate() method of this component, or * its corresponding {@link Renderer}.

*/ public Object getSubmittedValue() { return (this.submittedValue); } /** *

Set the submittedValue value of this {@link UIInput} component. * This method should only be used by the decode() and * validate() method of this component, or * its corresponding {@link Renderer}.

* * @param submittedValue The new submitted value */ public void setSubmittedValue(Object submittedValue) { this.submittedValue = submittedValue; } public void setValue(Object value) { super.setValue(value); // Mark the local value as set. setLocalValueSet(true); } /** *

Convenience method to reset this component's value to the * un-initialized state. This method does the following:

*

*

Call {@link #setValue} passing null.

*

*

Call {@link #setSubmittedValue} passing null.

*

*

Call {@link #setLocalValueSet} passing false.

*

*

Call {@link #setValid} passing true.

*

*

Upon return from this call if the instance had a * ValueBinding associated with it for the "value" * property, this binding is evaluated when {@link * UIOutput#getValue} is called. Otherwise, null is * returned from getValue().

*/ public void resetValue() { this.setValue(null); this.setSubmittedValue(null); this.setLocalValueSet(false); this.setValid(true); } /** *

The "localValueSet" state for this component. */ private boolean localValueSet; /** * Return the "local value set" state for this component. * Calls to setValue() automatically reset * this property to true. */ public boolean isLocalValueSet() { return localValueSet; } /** * Sets the "local value set" state for this component. */ public void setLocalValueSet(boolean localValueSet) { this.localValueSet = localValueSet; } /** *

The "required field" state for this component.

*/ private Boolean required; /** *

Return the "required field" state for this component.

*/ public boolean isRequired() { if (required != null) { return (this.required); } ValueExpression ve = getValueExpression("required"); if (ve != null) { try { return (Boolean.TRUE.equals(ve.getValue(getFacesContext().getELContext()))); } catch (ELException e) { throw new FacesException(e); } } else { return (false); } } private String requiredMessage; /** *

If there has been a call to {@link #setRequiredMessage} on this * instance, return the message. Otherwise, call {@link #getValueExpression} * passing the key "requiredMessage", get the result of the expression, and return it. * Any {@link ELException}s thrown during the call to getValue() * must be wrapped in a {@link FacesException} and rethrown. */ public String getRequiredMessage() { if (requiredMessage != null) { return requiredMessage; } ValueExpression ve = getValueExpression("requiredMessage"); if (ve != null) { try { return ((String) ve.getValue(getFacesContext().getELContext())); } catch (ELException e) { throw new FacesException(e); } } else { return (null); } } /** *

Override any {@link ValueExpression} set for the "requiredMessage" * with the literal argument provided to this method. Subsequent calls * to {@link #getRequiredMessage} will return this value;

* * @param message the literal message value to be displayed in the event * the user hasn't supplied a value and one is required. */ public void setRequiredMessage(String message) { requiredMessage = message; } private String converterMessage; /** *

If there has been a call to {@link #setConverterMessage} on this * instance, return the message. Otherwise, call {@link #getValueExpression} * passing the key "converterMessage", get the result of the expression, and return it. * Any {@link ELException}s thrown during the call to getValue() * must be wrapped in a {@link FacesException} and rethrown. */ public String getConverterMessage() { if (converterMessage != null) { return converterMessage; } ValueExpression ve = getValueExpression("converterMessage"); if (ve != null) { try { return ((String) ve.getValue(getFacesContext().getELContext())); } catch (ELException e) { throw new FacesException(e); } } else { return (null); } } /** *

Override any {@link ValueExpression} set for the "converterMessage" * with the literal argument provided to this method. Subsequent calls * to {@link #getConverterMessage} will return this value;

* * @param message the literal message value to be displayed in the event * conversion fails. */ public void setConverterMessage(String message) { converterMessage = message; } private String validatorMessage; /** *

If there has been a call to {@link #setValidatorMessage} on this * instance, return the message. Otherwise, call {@link #getValueExpression} * passing the key "validatorMessage", get the result of the expression, and return it. * Any {@link ELException}s thrown during the call to getValue() * must be wrapped in a {@link FacesException} and rethrown. */ public String getValidatorMessage() { if (validatorMessage != null) { return validatorMessage; } ValueExpression ve = getValueExpression("validatorMessage"); if (ve != null) { try { return ((String) ve.getValue(getFacesContext().getELContext())); } catch (ELException e) { throw new FacesException(e); } } else { return (null); } } /** *

Override any {@link ValueExpression} set for the "validatorMessage" * with the literal argument provided to this method. Subsequent calls * to {@link #getValidatorMessage} will return this value;

* * @param message the literal message value to be displayed in the event * validation fails. */ public void setValidatorMessage(String message) { validatorMessage = message; } private boolean valid = true; public boolean isValid() { return (this.valid); } public void setValid(boolean valid) { this.valid = valid; } /** *

Set the "required field" state for this component.

* * @param required The new "required field" state */ public void setRequired(boolean required) { this.required = required; } /** *

The immediate flag.

*/ private Boolean immediate; public boolean isImmediate() { if (this.immediate != null) { return (this.immediate); } ValueExpression ve = getValueExpression("immediate"); if (ve != null) { try { return (Boolean.TRUE.equals(ve.getValue(getFacesContext().getELContext()))); } catch (ELException e) { throw new FacesException(e); } } else { return (false); } } public void setImmediate(boolean immediate) { this.immediate = immediate; } /** *

Return a MethodBinding pointing at a * method that will be called during Process Validations * phase of the request processing lifecycle, to validate the current * value of this component.

* * @deprecated {@link #getValidators} should be used instead. */ public MethodBinding getValidator() { MethodBinding result = null; Validator[] curValidators = getValidators(); // go through our lisetners list and find the one and only // MethodBindingValidator instance, if present. if (null != curValidators) { for (int i = 0; i < curValidators.length; i++) { // We are guaranteed to have at most one instance of // MethodBindingValidator in the curValidators list. if (MethodBindingValidator.class == curValidators[i].getClass()) { result = ((MethodBindingValidator) curValidators[i]). getWrapped(); break; } } } return result; } /** *

Set a MethodBinding pointing at a * method that will be called during Process Validations * phase of the request processing lifecycle, to validate the current * value of this component.

*

*

Any method referenced by such an expression must be public, with * a return type of void, and accept parameters of type * {@link FacesContext}, {@link UIComponent}, and Object.

* * @param validatorBinding The new MethodBinding instance * @deprecated Use {@link #addValidator} instead, obtaining the * argument {@link Validator} by creating an instance of {@link * javax.faces.validator.MethodExpressionValidator}. */ public void setValidator(MethodBinding validatorBinding) { Validator[] curValidators = getValidators(); // see if we need to null-out, or replace an existing validator if (null != curValidators) { for (int i = 0; i < curValidators.length; i++) { // if we want to remove the validatorBinding if (null == validatorBinding) { // We are guaranteed to have at most one instance of // MethodBindingValidator in the curValidators // list. if (MethodBindingValidator.class == curValidators[i].getClass()) { removeValidator(curValidators[i]); return; } } // if we want to replace the validatorBinding else //noinspection ObjectEquality if (validatorBinding == curValidators[i]) { removeValidator(curValidators[i]); break; } } } addValidator(new MethodBindingValidator(validatorBinding)); } public MethodBinding getValueChangeListener() { MethodBinding result = null; ValueChangeListener[] curListeners = getValueChangeListeners(); // go through our lisetners list and find the one and only // MethodBindingValueChangeListener instance, if present. if (null != curListeners) { for (int i = 0; i < curListeners.length; i++) { // We are guaranteed to have at most one instance of // MethodBindingValueChangeListener in the curListeners list. if (MethodBindingValueChangeListener.class == curListeners[i].getClass()) { result = ((MethodBindingValueChangeListener) curListeners[i]). getWrapped(); break; } } } return result; } /** * {@inheritDoc} * * @deprecated Use {@link #addValueChangeListener} instead, obtaining the * argument {@link ValueChangeListener} by creating an instance of {@link * javax.faces.event.MethodExpressionValueChangeListener}. */ public void setValueChangeListener(MethodBinding valueChangeListener) { ValueChangeListener[] curListeners = getValueChangeListeners(); // see if we need to null-out, or replace an existing listener if (null != curListeners) { for (int i = 0; i < curListeners.length; i++) { // if we want to remove the valueChangeListener if (null == valueChangeListener) { // We are guaranteed to have at most one instance of // MethodBindingValueChangeListener in the curListeners // list. if (MethodBindingValueChangeListener.class == curListeners[i].getClass()) { removeFacesListener(curListeners[i]); return; } } // if we want to replace the valueChangeListener else //noinspection ObjectEquality if (valueChangeListener == curListeners[i]) { removeFacesListener(curListeners[i]); break; } } } addValueChangeListener(new MethodBindingValueChangeListener(valueChangeListener)); } // ----------------------------------------------------- UIComponent Methods /** *

Specialized decode behavior on top of that provided by the * superclass. In addition to the standard * processDecodes behavior inherited from {@link * UIComponentBase}, calls validate() if the the * immediate property is true; if the component is * invalid afterwards or a RuntimeException is thrown, * calls {@link FacesContext#renderResponse}.

* * @throws NullPointerException {@inheritDoc} */ public void processDecodes(FacesContext context) { if (context == null) { throw new NullPointerException(); } // Skip processing if our rendered flag is false if (!isRendered()) { return; } super.processDecodes(context); if (isImmediate()) { executeValidate(context); } } /** *

In addition to the standard processValidators behavior * inherited from {@link UIComponentBase}, calls validate() * if the immediate property is false (which is the * default); if the component is invalid afterwards, calls * {@link FacesContext#renderResponse}. * If a RuntimeException is thrown during * validation processing, calls {@link FacesContext#renderResponse} * and re-throw the exception. *

* * @throws NullPointerException {@inheritDoc} */ public void processValidators(FacesContext context) { if (context == null) { throw new NullPointerException(); } // Skip processing if our rendered flag is false if (!isRendered()) { return; } super.processValidators(context); if (!isImmediate()) { executeValidate(context); } } /** *

In addition to the standard processUpdates behavior * inherited from {@link UIComponentBase}, calls * updateModel(). * If the component is invalid afterwards, calls * {@link FacesContext#renderResponse}. * If a RuntimeException is thrown during * update processing, calls {@link FacesContext#renderResponse} * and re-throw the exception. *

* * @throws NullPointerException {@inheritDoc} */ public void processUpdates(FacesContext context) { if (context == null) { throw new NullPointerException(); } // Skip processing if our rendered flag is false if (!isRendered()) { return; } super.processUpdates(context); try { updateModel(context); } catch (RuntimeException e) { context.renderResponse(); throw e; } if (!isValid()) { context.renderResponse(); } } /** * @throws NullPointerException {@inheritDoc} */ public void decode(FacesContext context) { if (context == null) { throw new NullPointerException(); } // Force validity back to "true" setValid(true); super.decode(context); } /** *

Perform the following algorithm to update the model data * associated with this {@link UIInput}, if any, as appropriate.

*
    *
  • If the valid property of this component is * false, take no further action.
  • *
  • If the localValueSet property of this component is * false, take no further action.
  • *
  • If no {@link ValueExpression} for value exists, * take no further action.
  • *
  • Call setValue() method of the {@link ValueExpression} * to update the value that the {@link ValueExpression} points at.
  • *
  • If the setValue() method returns successfully: *
      *
    • Clear the local value of this {@link UIInput}.
    • *
    • Set the localValueSet property of this * {@link UIInput} to false.
    • *
  • *
  • If the setValue() method call fails: *
      *
    • Enqueue an error message by calling addMessage() * on the specified {@link FacesContext} instance.
    • *
    • Set the valid property of this {@link UIInput} * to false.
    • *
  • *
* * @param context {@link FacesContext} for the request we are processing * @throws NullPointerException if context * is null */ public void updateModel(FacesContext context) { if (context == null) { throw new NullPointerException(); } if (!isValid() || !isLocalValueSet()) { return; } ValueExpression ve = getValueExpression("value"); if (ve != null) { try { ve.setValue(context.getELContext(), getLocalValue()); setValue(null); setLocalValueSet(false); } catch (ELException e) { String messageStr = e.getMessage(); Throwable result = e.getCause(); while (null != result && result.getClass().isAssignableFrom(ELException.class)) { messageStr = result.getMessage(); result = result.getCause(); } FacesMessage message; if (null == messageStr) { message = MessageFactory.getMessage(context, UPDATE_MESSAGE_ID, MessageFactory.getLabel( context, this)); } else { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, messageStr, messageStr); } LOGGER.log(Level.SEVERE, message.getSummary(), result); context.addMessage(getClientId(context), message); setValid(false); } catch (IllegalArgumentException e) { FacesMessage message = MessageFactory.getMessage(context, UPDATE_MESSAGE_ID, MessageFactory.getLabel( context, this)); LOGGER.log(Level.SEVERE, message.getSummary(), e); context.addMessage(getClientId(context), message); setValid(false); } catch (Exception e) { FacesMessage message = MessageFactory.getMessage(context, UPDATE_MESSAGE_ID, MessageFactory.getLabel( context, this)); LOGGER.log(Level.SEVERE, message.getSummary(), e); context.addMessage(getClientId(context), message); setValid(false); } } } // ------------------------------------------------------ Validation Methods /** *

Perform the following algorithm to validate the local value of * this {@link UIInput}.

*
    *
  • Retrieve the submitted value with getSubmittedValue(). * If this returns null, exit without further processing. (This * indicates that no value was submitted for this component.)
  • *

    *

  • Convert the submitted value into a "local value" of the * appropriate data type by calling {@link #getConvertedValue}.
  • *

    *

  • Validate the property by calling {@link #validateValue}.
  • *

    *

  • If the valid property of this component is still * true, retrieve the previous value of the component * (with getValue()), store the new local value using * setValue(), and reset the submitted value to * null. If the local value is different from * the previous value of this component, fire a * {@link ValueChangeEvent} to be broadcast to all interested * listeners.
  • *
*

*

Application components implementing {@link UIInput} that wish to * perform validation with logic embedded in the component should perform * their own correctness checks, and then call the * super.validate() method to perform the standard * processing described above.

* * @param context The {@link FacesContext} for the current request * @throws NullPointerException if context * is null */ public void validate(FacesContext context) { if (context == null) { throw new NullPointerException(); } // Submitted value == null means "the component was not submitted // at all"; validation should not continue Object submittedValue = getSubmittedValue(); if (submittedValue == null) { return; } Object newValue = null; try { newValue = getConvertedValue(context, submittedValue); } catch (ConverterException ce) { addConversionErrorMessage(context, ce, submittedValue); setValid(false); } validateValue(context, newValue); // If our value is valid, store the new value, erase the // "submitted" value, and emit a ValueChangeEvent if appropriate if (isValid()) { Object previous = getValue(); setValue(newValue); setSubmittedValue(null); if (compareValues(previous, newValue)) { queueEvent(new ValueChangeEvent(this, previous, newValue)); } } } /** *

Convert the submitted value into a "local value" of the * appropriate data type, if necessary. Employ the following * algorithm to do so:

*
    *
  • If a Renderer is present, call * getConvertedValue() to convert the submitted * value.
  • *
  • If no Renderer is present, and the submitted * value is a String, locate a {@link Converter} as follows: *
      *
    • If getConverter() returns a non-null {@link Converter}, * use that instance.
    • *
    • Otherwise, if a value binding for value exists, * call getType() on it. *
        *
      • If this call returns null, assume the output * type is String and perform no conversion.
      • *
      • Otherwise, call * Application.createConverter(Class) * to locate any registered {@link Converter} capable of * converting data values of the specified type.
      • *
      *
    • *
    *
  • If a {@link Converter} instance was located, call its * getAsObject() method to perform the conversion. * If conversion fails: *
      *
    • Enqueue an appropriate error message by calling the * addMessage() method on the * FacesContext.
    • *
    • Set the valid property * on this component to false
    • *
  • *
  • Otherwise, use the submitted value without any conversion
  • *
* *

*

*

*

This method can be overridden by subclasses for more specific * behavior.

*/ protected Object getConvertedValue(FacesContext context, Object newSubmittedValue) throws ConverterException { Renderer renderer = getRenderer(context); Object newValue; if (renderer != null) { newValue = renderer.getConvertedValue(context, this, newSubmittedValue); } else if (newSubmittedValue instanceof String) { // If there's no Renderer, and we've got a String, // run it through the Converter (if any) Converter converter = getConverterWithType(context); if (converter != null) { newValue = converter.getAsObject(context, this, (String) newSubmittedValue); } else { newValue = newSubmittedValue; } } else { newValue = newSubmittedValue; } return newValue; } /** *

Set the "valid" property according to the below algorithm.

*

*

    *

    *

  • If the valid property on this component is still * true, and the required property is also * true, ensure that the local value is not empty (where "empty" is * defined as null or a zero-length String. If the local * value is empty: *
      *
    • Enqueue an appropriate error message by calling the * addMessage() method on the FacesContext * instance for the current request. If the {@link #getRequiredMessage} * returns non-null, use the value as the summary * and detail in the {@link FacesMessage} that * is enqueued on the FacesContext, otherwise * use the message for the {@link #REQUIRED_MESSAGE_ID}. *
    • *
    • Set the valid property on this component to * false.
    • *
  • *
  • If the valid property on this component is still * true, and the local value is not empty, call the * validate() method of each {@link Validator} * registered for this {@link UIInput}, followed by the method * pointed at by the validatorBinding property (if any). * If any of these validators or the method throws a * {@link ValidatorException}, catch the exception, add * its message (if any) to the {@link FacesContext}, and set * the valid property of this component to false.
  • *

    *

*/ protected void validateValue(FacesContext context, Object newValue) { // If our value is valid, enforce the required property if present if (isValid() && isRequired() && isEmpty(newValue)) { String requiredMessageStr = getRequiredMessage(); FacesMessage message; if (null != requiredMessageStr) { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, requiredMessageStr, requiredMessageStr); } else { message = MessageFactory.getMessage(context, REQUIRED_MESSAGE_ID, MessageFactory.getLabel( context, this)); } context.addMessage(getClientId(context), message); setValid(false); } // If our value is valid and not empty, call all validators if (isValid() && !isEmpty(newValue)) { if (this.validators != null) { for (Validator validator : this.validators) { try { validator.validate(context, this, newValue); } catch (ValidatorException ve) { // If the validator throws an exception, we're // invalid, and we need to add a message setValid(false); FacesMessage message; String validatorMessageString = getValidatorMessage(); if (null != validatorMessageString) { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, validatorMessageString, validatorMessageString); message.setSeverity(FacesMessage.SEVERITY_ERROR); } else { message = ve.getFacesMessage(); } if (message != null) { context.addMessage(getClientId(context), message); } } } } } } /** *

Return true if the new value is different from the * previous value.

* * @param previous old value of this component (if any) * @param value new value of this component (if any) */ protected boolean compareValues(Object previous, Object value) { if (previous == null) { return (value != null); } else if (value == null) { return (true); } else { return (!(previous.equals(value))); } } /** * Executes validation logic. */ private void executeValidate(FacesContext context) { try { validate(context); } catch (RuntimeException e) { context.renderResponse(); throw e; } if (!isValid()) { context.renderResponse(); } } private static boolean isEmpty(Object value) { if (value == null) { return (true); } else if ((value instanceof String) && (((String) value).length() < 1)) { return (true); } else if (value.getClass().isArray()) { if (0 == java.lang.reflect.Array.getLength(value)) { return (true); } } else if (value instanceof List) { if (((List) value).isEmpty()) { return (true); } } return (false); } /** *

The set of {@link Validator}s associated with this * UIComponent.

*/ List validators = null; /** *

Add a {@link Validator} instance to the set associated with * this {@link UIInput}.

* * @param validator The {@link Validator} to add * @throws NullPointerException if validator * is null */ public void addValidator(Validator validator) { if (validator == null) { throw new NullPointerException(); } if (validators == null) { //noinspection CollectionWithoutInitialCapacity validators = new ArrayList(); } validators.add(validator); } /** *

Return the set of registered {@link Validator}s for this * {@link UIInput} instance. If there are no registered validators, * a zero-length array is returned.

*/ public Validator[] getValidators() { if (validators == null) { return EMPTY_VALIDATOR; } else { return (validators.toArray(new Validator[validators.size()])); } } /** *

Remove a {@link Validator} instance from the set associated with * this {@link UIInput}, if it was previously associated. * Otherwise, do nothing.

* * @param validator The {@link Validator} to remove */ public void removeValidator(Validator validator) { if (validators != null) { validators.remove(validator); } } // ------------------------------------------------ Event Processing Methods /** *

Add a new {@link ValueChangeListener} to the set of listeners * interested in being notified when {@link ValueChangeEvent}s occur.

* * @param listener The {@link ValueChangeListener} to be added * @throws NullPointerException if listener * is null */ public void addValueChangeListener(ValueChangeListener listener) { addFacesListener(listener); } /** *

Return the set of registered {@link ValueChangeListener}s for this * {@link UIInput} instance. If there are no registered listeners, * a zero-length array is returned.

*/ public ValueChangeListener[] getValueChangeListeners() { return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class); } /** *

Remove an existing {@link ValueChangeListener} (if any) from the * set of listeners interested in being notified when * {@link ValueChangeEvent}s occur.

* * @param listener The {@link ValueChangeListener} to be removed * @throws NullPointerException if listener * is null */ public void removeValueChangeListener(ValueChangeListener listener) { removeFacesListener(listener); } // ----------------------------------------------------- StateHolder Methods private Object[] values; public Object saveState(FacesContext context) { if (values == null) { values = new Object[9]; } values[0] = super.saveState(context); values[1] = localValueSet; values[2] = required; values[3] = requiredMessage; values[4] = converterMessage; values[5] = validatorMessage; values[6] = valid; values[7] = immediate; values[8] = saveAttachedState(context, validators); return (values); } public void restoreState(FacesContext context, Object state) { values = (Object[]) state; super.restoreState(context, values[0]); localValueSet = (Boolean) values[1]; required = (Boolean) values[2]; requiredMessage = ((String) values[3]); converterMessage = ((String) values[4]); validatorMessage = ((String) values[5]); valid = (Boolean) values[6]; immediate = (Boolean) values[7]; List restoredValidators; Iterator iter; if (null != (restoredValidators = TypedCollections.dynamicallyCastList((List) restoreAttachedState(context, values[8]), Validator.class))) { // if there were some validators registered prior to this // method being invoked, merge them with the list to be // restored. if (null != validators) { iter = restoredValidators.iterator(); while (iter.hasNext()) { validators.add(iter.next()); } } else { validators = restoredValidators; } } } private Converter getConverterWithType(FacesContext context) { Converter converter = getConverter(); if (converter != null) { return converter; } ValueExpression valueExpression = getValueExpression("value"); if (valueExpression == null) { return null; } Class converterType; try { converterType = valueExpression.getType(context.getELContext()); } catch (ELException e) { throw new FacesException(e); } // if converterType is null, String, or Object, assume // no conversion is needed if (converterType == null || converterType == String.class || converterType == Object.class) { return null; } // if getType returns a type for which we support a default // conversion, acquire an appropriate converter instance. try { Application application = context.getApplication(); return application.createConverter(converterType); } catch (Exception e) { return (null); } } private void addConversionErrorMessage(FacesContext context, ConverterException ce, Object value) { FacesMessage message; String converterMessageString = getConverterMessage(); if (null != converterMessageString) { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, converterMessageString, converterMessageString); } else { message = ce.getFacesMessage(); if (message == null) { message = MessageFactory.getMessage(context, CONVERSION_MESSAGE_ID); if (message.getDetail() == null) { message.setDetail(ce.getMessage()); } } } context.addMessage(getClientId(context), message); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy