Package org.richfaces.component

Source Code of org.richfaces.component.UIOrderingBaseComponent$UpdateModelCommand

/**
*
*/
package org.richfaces.component;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.el.EvaluationException;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import org.ajax4jsf.component.UIDataAdaptor;
import org.ajax4jsf.model.DataComponentState;
import org.ajax4jsf.model.RepeatState;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.iterators.EmptyIterator;
import org.apache.commons.collections.iterators.FilterIterator;
import org.richfaces.component.util.MessageUtil;

/**
* @author Nick Belaevski
*         mailto:nbelaevski@exadel.com
*         created 16.11.2007
* @since 3.2
*/
public abstract class UIOrderingBaseComponent extends UIDataAdaptor implements EditableValueHolder {

  private boolean localValueSet;

  private List validators = null;
  private MethodBinding validator;

  public static final Predicate isColumn = new Predicate() {
    public boolean evaluate(Object input) {
      return (input instanceof javax.faces.component.UIColumn || input instanceof Column) &&
          ((UIComponent) input).isRendered();
    }
  };

  protected boolean isSuitableValue(Object value, Object restoredObject) {
    if (value instanceof Object[]) {
      Object[] objects = (Object[]) value;
      for (int i = 0; i < objects.length; i++) {
        Object object = objects[i];
     
        if (object != null && object.equals(restoredObject)) {
          return true;
        }
      }

      return false;
    } else {
      if (value != null) {
        return ((Collection) value).contains(restoredObject);
      } else {
        return false;
      }
    }
  }
 
  public abstract boolean isOrderControlsVisible();
  public abstract void setOrderControlsVisible(boolean visible);
 
  public abstract boolean isFastOrderControlsVisible();
  public abstract void setFastOrderControlsVisible(boolean visible);

  public Object saveState(FacesContext faces) {
    Object[] state = new Object[4];

    state[0] = super.saveState(faces);
 
    state[1] = saveAttachedState(faces, validators);
    state[2] = saveAttachedState(faces, validator);

    state[3] = localValueSet ? Boolean.TRUE : Boolean.FALSE;

    return state;
  }

  public void restoreState(FacesContext faces, Object object) {
    Object[] state = (Object[]) object;

    super.restoreState(faces, state[0]);

    validators = (List) restoreAttachedState(faces, state[1]);
    validator = (MethodBinding) restoreAttachedState(faces, state[2]);

    localValueSet = ((Boolean) state[3]).booleanValue();
  }

  protected DataComponentState createComponentState() {
    return new RepeatState();
  }

  public Iterator columns() {
    return new FilterIterator(getChildren().iterator(), isColumn);
  }

  protected Iterator dataChildren() {
    if (getChildCount() != 0) {
      return columns();
    } else {
      return EmptyIterator.INSTANCE;
    }
  }

  protected Iterator fixedChildren() {
    Map facets = getFacets();
    if (facets != null) {
      return facets.values().iterator();
    } else {
      return EmptyIterator.INSTANCE;
    }
  }

  //validators
  public MethodBinding getValidator() {
    return validator;
  }

  public void setValidator(MethodBinding validatorBinding) {
    this.validator = validatorBinding;
  }

  public Validator[] getValidators() {

    if (validators == null) {
      return new Validator[0];
    } else {
      return (Validator[]) validators.toArray(new Validator[validators.size()]);
    }
  }

  public void addValidator(Validator validator) {
    if (validator == null) {
      throw new NullPointerException();
    }

    if (validators == null) {
      validators = new ArrayList();
    }

    validators.add(validator);
  }

  public void removeValidator(Validator validator) {
    if (validators != null) {
      validators.remove(validator);
    }
  }
  //validators end
 
  public boolean isLocalValueSet() {
    return localValueSet;
  }

  public void setLocalValueSet(boolean localValueSet) {
    this.localValueSet = localValueSet;
  }

  protected DataModel createDataModel(Object value) {
    DataModel dataModel;
       
        if (value == null) {
            dataModel = new ListDataModel(Collections.EMPTY_LIST);
        } else if (value instanceof List) {
          dataModel = new ListDataModel((List) value);
        } else if (Object[].class.isAssignableFrom(value.getClass())) {
          dataModel = new ArrayDataModel((Object[]) value);
        } else {
          throw new IllegalArgumentException();
        }
       
        return dataModel;
  }


  /**
   * @exception NullPointerException {@inheritDoc}    
   */
  public void decode(FacesContext context) {

    if (context == null) {
      throw new NullPointerException();
    }

    // Force validity back to "true"
    setValid(true);
    super.decode(context);
  }

  /**
   * <p>Specialized decode behavior on top of that provided by the
   * superclass.  In addition to the standard
   * <code>processDecodes</code> behavior inherited from {@link
   * UIComponentBase}, calls <code>validate()</code> if the the
   * <code>immediate</code> property is true; if the component is
   * invalid afterwards or a <code>RuntimeException</code> is thrown,
   * calls {@link FacesContext#renderResponse}</p>
   * @exception 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);
    }
  }

  /**
   * Executes validation logic.
   */
  protected void executeValidate(FacesContext context) {
    try {
      validate(context);
    } catch (RuntimeException e) {
      context.renderResponse();
      throw e;
    }

    if (!isValid()) {
      context.renderResponse();
    }
  }


  public abstract void validate(FacesContext context);
 
  /**
   * <p>In addition to the standard <code>processValidators</code> behavior
   * inherited from {@link UIComponentBase}, calls <code>validate()</code>
   * if the <code>immediate</code> property is false (which is the
   * default);  if the component is invalid afterwards, calls
   * {@link FacesContext#renderResponse}.
   * If a <code>RuntimeException</code> is thrown during
   * validation processing, calls {@link FacesContext#renderResponse}
   * and re-throw the exception.
   * </p>
   * @exception 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);
    }
  }

  /**
   *
   * <p>Set the "valid" property according to the below algorithm.</p>
   *
   * <ul>
   *
   * <li>If the <code>valid</code> property on this component is still
   *     <code>true</code>, and the <code>required</code> property is also
   *     true, ensure that the local value is not empty (where "empty" is
   *     defined as <code>null</code> or a zero-length String.  If the local
   *     value is empty:
   *     <ul>
   *     <li>Enqueue an appropriate error message by calling the
   *         <code>addMessage()</code> method on the <code>FacesContext</code>
   *         instance for the current request.</li>
   *     <li>Set the <code>valid</code> property on this component to
   *         <code>false</code>.</li>
   *     </ul></li>
   * <li>If the <code>valid</code> property on this component is still
   *     <code>true</code>, and the local value is not empty, call the
   *     <code>validate()</code> method of each {@link Validator}
   *     registered for this {@link UIInput}, followed by the method
   *     pointed at by the <code>validatorBinding</code> 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 <code>valid</code> property of this component to false.</li>
   *
   * </ul>
   *
   */
  protected void validateValue(FacesContext context, Object newValue) {
      validateListValue(context, newValue, isEmpty(newValue), isRequired());
  }

  protected void validateListValue(FacesContext context, Object newValue,
           boolean isEmpty, boolean isRequired) {
      // If our value is valid, enforce the required property if present
      requiredValidation(context, newValue, isEmpty, isRequired);
       
      // If our value is valid and not empty, call all validators
      processingValidators(context, newValue, isEmpty);
  }
 
  protected void requiredValidation(FacesContext context, Object newValue, boolean isRequired, boolean isEmpty) {
      if (isValid() && isRequired && isEmpty) {
    FacesMessage message = MessageUtil.getMessage(context, UIInput.REQUIRED_MESSAGE_ID,
                                new Object[] {MessageUtil.getLabel(context, this)});
    message.setSeverity(FacesMessage.SEVERITY_ERROR);
     
    context.addMessage(getClientId(context), message);
    setValid(false);
      }
  }
 
  protected void processingValidators(FacesContext context, Object newValue, boolean isEmpty) {
      if (isValid() && !isEmpty) {
    Validator[] validators = getValidators();
    for (int i = 0; i < validators.length; i++) {
      Validator validator = (Validator) validators[i];
      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 = ve.getFacesMessage();
        if (message != null) {
          message.setSeverity(FacesMessage.SEVERITY_ERROR);
          context.addMessage(getClientId(context), message);
        }
      }
    }

    MethodBinding validator = getValidator();
    if (validator != null) {
      try {
        validator.invoke(context,
            new Object[] { context, this, newValue});
      }
      catch (EvaluationException ee) {
        if (ee.getCause() instanceof ValidatorException) {
          ValidatorException ve =
            (ValidatorException) ee.getCause();

          // If the validator throws an exception, we're
          // invalid, and we need to add a message
          setValid(false);
          FacesMessage message = ve.getFacesMessage();
          if (message != null) {
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(getClientId(context), message);
          }
        } else {
          // Otherwise, rethrow the EvaluationException
          throw ee;
        }
      }
    }
      }
  }
 
  /**
   * <p>In addition to the standard <code>processUpdates</code> behavior
   * inherited from {@link UIComponentBase}, calls
   * <code>updateModel()</code>.
   * If the component is invalid afterwards, calls
   * {@link FacesContext#renderResponse}.
   * If a <code>RuntimeException</code> is thrown during
   * update processing, calls {@link FacesContext#renderResponse}
   * and re-throw the exception.
   * </p>
   * @exception 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();
    }
  }

  public abstract void updateModel(FacesContext context);

  protected interface UpdateModelCommand {
    public void execute(FacesContext context);
  }

  protected interface DataAdder {
    Object getContainer();
    void add(Object object);
  }

  protected void updateModel(FacesContext context, UpdateModelCommand command) {
    try {
      command.execute(context);
    } catch (EvaluationException e) {
      String messageStr = e.getMessage();
      FacesMessage message = null;
      if (null == messageStr) {
        message =
          MessageUtil.getMessage(context, UIInput.UPDATE_MESSAGE_ID,
              new Object[] {MessageUtil.getLabel(context, this)});
      }
      else {
        message = new FacesMessage(messageStr);
      }
      message.setSeverity(FacesMessage.SEVERITY_ERROR);
      context.addMessage(getClientId(context), message);
      setValid(false);
    }
    catch (FacesException e) {
      FacesMessage message =
        MessageUtil.getMessage(context, UIInput.UPDATE_MESSAGE_ID,
          new Object[] {MessageUtil.getLabel(context, this)});
      message.setSeverity(FacesMessage.SEVERITY_ERROR);
      context.addMessage(getClientId(context), message);
      setValid(false);
    } catch (IllegalArgumentException e) {
      FacesMessage message =
        MessageUtil.getMessage(context, UIInput.UPDATE_MESSAGE_ID,
          new Object[] {MessageUtil.getLabel(context, this)});
      message.setSeverity(FacesMessage.SEVERITY_ERROR);
      context.addMessage(getClientId(context), message);
      setValid(false);
    } catch (Exception e) {
      FacesMessage message =
        MessageUtil.getMessage(context, UIInput.UPDATE_MESSAGE_ID,
          new Object[] {MessageUtil.getLabel(context, this)});
      message.setSeverity(FacesMessage.SEVERITY_ERROR);
      context.addMessage(getClientId(context), message);
      setValid(false);
    }
  }
 
  /**
   * <p>Return <code>true</code> if the new value is different from the
   * previous value.</p>
   *
   * @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 {
      if (previous instanceof Object[]) {
        return !Arrays.equals((Object[]) previous, (Object[]) value);
      } else {
        return (!(previous.equals(value)));
      }
    }

  }

  protected void addConversionErrorMessage(FacesContext context,
      ConverterException ce, Object value) {
    FacesMessage message = ce.getFacesMessage();
    if (message == null) {
      message = MessageUtil.getMessage(context, UIInput.CONVERSION_MESSAGE_ID,
          new Object[] {MessageUtil.getLabel(context, this)});
      if (message.getDetail() == null) {
        message.setDetail(ce.getMessage());
      }
    }

    message.setSeverity(FacesMessage.SEVERITY_ERROR);
    context.addMessage(getClientId(context), message);
  }
 
  protected 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 (0 == ((List) value).size()) {
        return (true);
      }
    }
    return (false);
  }

  protected Object createContainer(ArrayList data, Object object) {
    if (object != null) {
      Class objectClass = object.getClass();
      Class componentType = objectClass.getComponentType();
      if (componentType != null) {
        return data.toArray((Object[]) Array.newInstance(componentType, data.size()));
      }
    }
   
    data.trimToSize();
    return data;
  }

  public abstract ItemState getItemState();
 
  public interface ItemState {
    public boolean isSelected();
    public boolean isActive();
  }

  private Converter getConverterForType(FacesContext context, Class type) {
    if (!Object.class.equals(type)) {
      Application application = context.getApplication();
      return application.createConverter(type);
    }

    return null;
  }
 
  public Converter getConverterForValue(FacesContext context) {
    ValueBinding binding = this.getValueBinding("value");
    if (binding != null) {
      Class type = binding.getType(context);
      if (type != null) {
        Class componentType = type.getComponentType();
        if (componentType != null) {
          return getConverterForType(context, componentType);
        } else {
          //support for generics introspection
        }
      }
    }
   
    return null;
  }
 
}
TOP

Related Classes of org.richfaces.component.UIOrderingBaseComponent$UpdateModelCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.