Package org.richfaces.component

Source Code of org.richfaces.component.UIOrderingList$ValueHolder

package org.richfaces.component;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.faces.application.FacesMessage;
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.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
import javax.faces.model.DataModel;

import org.ajax4jsf.Messages;
import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.model.ExtendedDataModel;
import org.ajax4jsf.model.SequenceDataModel;
import org.richfaces.component.util.MessageUtil;
import org.richfaces.model.OrderingListDataModel;

public abstract class UIOrderingList extends UIOrderingBaseComponent {

  protected void processDecodes(FacesContext faces, Object argument) {
    if (!this.isRendered())
      return;
    this.decode(faces);

    SubmittedValue submittedValue = UIOrderingList.this.submittedValueHolder;
    if (submittedValue != null) {
      Object modelValue = getValue();
      Iterator iterator = submittedValue.dataMap.entrySet().iterator();
      while (iterator.hasNext()) {
        Entry entry = (Entry) iterator.next();
        Object value = entry.getValue();
       
        if (!isSuitableValue(modelValue, value)) {
          String messageText = Messages.getMessage(
              Messages.INVALID_VALUE, MessageUtil.getLabel(faces, this), value);
         
          FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, messageText, null);
          faces.addMessage(this.getClientId(faces), message);

          setValid(false);
          break;
        }
      }
    }
   
        this.iterate(faces, decodeVisitor, argument);

        if (isImmediate()) {
      executeValidate(faces);
    }
   
        if (!isValid()) {
            faces.renderResponse();
        }
  }

  private ValueHolder valueHolder;

  protected static final class SubmittedValue implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 5860506816451180551L;
   
    private Map dataMap;
    private Set selection;
    private Object activeItem;
   
    private boolean _null = false;

    public SubmittedValue(Map dataMap, Set selection, Object activeItem) {
      this.dataMap = dataMap;
      this.selection = selection;
      this.activeItem = activeItem;
    }

    public void setNull() {
      _null = true;
    }
   
    public boolean isNull() {
      return _null;
    }
   
    public void resetDataModel() {
      if (_null) {
        this.dataMap = null;
      }
    }
  }

  private final class ModelItemState implements ItemState {
    private Collection selectedItems;
    private Object activeItem;

    public ModelItemState(Collection selectedItems, Object activeItem) {
      super();
      this.selectedItems = selectedItems;
      this.activeItem = activeItem;
    }

    public boolean isSelected() {
      return selectedItems != null && selectedItems.contains(getRowData());
    }

    public boolean isActive() {
      return activeItem != null && activeItem.equals(getRowData());
    }
  }

  protected ExtendedDataModel createDataModel() {
    Map modelMap = null;

    if (submittedValueHolder != null) {
      modelMap = submittedValueHolder.dataMap;
    }
   
    if (modelMap != null) {
      OrderingListDataModel dataModel = new OrderingListDataModel();
      dataModel.setWrappedData(modelMap);
      return dataModel;
    } else {
      DataModel dataModel = createDataModel(getValue());
      return new SequenceDataModel(dataModel);
    }
  }

  private transient SubmittedValue submittedValueHolder = null;
 
  public final static class ValueHolder implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = -4216115242421460529L;
   
    private Object value;
   
    private Set selection;
    private boolean selectionSet;

    private Object activeItem;
    private boolean activeItemSet;

    public boolean isTransient() {
      //TODO null collection == [] ?
      return value == null && (selection == null || selection.isEmpty()) && !selectionSet &&
      activeItem == null && !activeItemSet;
    }

    public void restoreState(FacesContext context, UIOrderingList list, Object _state) {
      Object[] state = (Object[]) _state;
     
      value = restoreAttachedState(context, state[0]);
     
      selection = (Set) restoreAttachedState(context, state[1]);
      selectionSet = Boolean.TRUE.equals(state[2]);
     
      activeItem = restoreAttachedState(context, state[3]);
      activeItemSet = Boolean.TRUE.equals(state[4]);
    }

    public Object saveState(FacesContext context, final UIOrderingList list) {
//      Object rowKey = list.getRowKey();
//
//      final HashSet selectionKeySet = new HashSet();
//      final Object[] activeItemSet = new Object[1];
//      try {
//        list.walk(context, new DataVisitor() {
//
//          public void process(FacesContext context, Object rowKey,
//              Object argument) throws IOException {
//
//            list.setRowKey(context, rowKey);
//            Object data = list.getRowData();
//           
//            if (data != null) {
//              if (data.equals(activeItem)) {
//                activeItemSet[0] = rowKey;
//              }
//             
//              if (selection != null && selection.contains(data)) {
//                selectionKeySet.add(rowKey);
//              }
//            }
//          }
//         
//        }, null);
//      } catch (IOException e) {
//        throw new FacesException(e.getLocalizedMessage(), e);
//      }

      Object[] state = new Object[5];
     
      state[0] = saveAttachedState(context, value);
      state[1] = saveAttachedState(context, selection);
      state[2] = this.selectionSet ? Boolean.TRUE : Boolean.FALSE;
     
      state[3] = saveAttachedState(context, activeItem);
      state[4] = this.activeItemSet ? Boolean.TRUE : Boolean.FALSE;

      return state;
    }

    public void setTransient(boolean newTransientValue) {
      if (newTransientValue) {
        throw new IllegalArgumentException();
      }
    }
  }

  public void addValueChangeListener(ValueChangeListener listener) {
    addFacesListener(listener);
  }


  public abstract MethodBinding getValueChangeListener();

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

  public abstract boolean isImmediate();

  public abstract boolean isRequired();

  public abstract boolean isValid();


  public void removeValueChangeListener(ValueChangeListener listener) {
    removeFacesListener(listener);
  }

  public void setSubmittedString(Map submittedString, Set selection, Object activeItem) {
    this.submittedValueHolder = new SubmittedValue(submittedString, selection, activeItem);
  }

  public Object getSubmittedValue() {
    return submittedValueHolder;
  }

  public void setSubmittedValue(Object object) {
    this.submittedValueHolder = (SubmittedValue) object;
  }

  protected Object saveIterationState() {
    return valueHolder;
  }

  protected void restoreIterationState(Object object) {
    this.valueHolder = (ValueHolder) object;
  }

  public abstract void setImmediate(boolean immediate);

  public abstract void setRequired(boolean required);

  public abstract void setValid(boolean valid);

  public abstract void setValueChangeListener(MethodBinding valueChangeMethod);

  public abstract Converter getConverter();

  public abstract void setConverter(Converter converter);

  /**
   * <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);
  }

  /**
   * <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);
  }

  /**
   * <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);
  }

  /**
   * <p>In addition to to the default {@link UIComponent#broadcast}
   * processing, pass the {@link ValueChangeEvent} being broadcast to the
   * method referenced by <code>valueChangeListener</code> (if any).</p>
   *
   * @param event {@link FacesEvent} to be broadcast
   *
   * @exception AbortProcessingException Signal the JavaServer Faces
   *  implementation that no further processing on the current event
   *  should be performed
   * @exception IllegalArgumentException if the implementation class
   *  of this {@link FacesEvent} is not supported by this component
   * @exception NullPointerException if <code>event</code> is
   * <code>null</code>
   */
  public void broadcast(FacesEvent event)
  throws AbortProcessingException {

    // Perform standard superclass processing
    super.broadcast(event);

    if (event instanceof ValueChangeEvent) {
      MethodBinding method = getValueChangeListener();
      if (method != null) {
        FacesContext context = getFacesContext();
        method.invoke(context, new Object[] { event });
      }
    }

  }

  protected final UpdateModelCommand updateActiveItemCommand = new UpdateModelCommand() {

    public void execute(FacesContext context) {
      if (valueHolder.activeItemSet) {
        ValueBinding vb = getValueBinding("activeItem");
        if (vb != null) {
          vb.setValue(context, valueHolder.activeItem);
          valueHolder.activeItem = null;
          valueHolder.activeItemSet = false;
        }
      }
    }
   
  };

  protected final UpdateModelCommand updateSelectionCommand = new UpdateModelCommand() {

    public void execute(FacesContext context) {
      if (valueHolder.selectionSet) {
        ValueBinding vb = getValueBinding("selection");
        if (vb != null) {
          vb.setValue(context, valueHolder.selection);
          valueHolder.selection = null;
          valueHolder.selectionSet = false;
        }
      }
    }
   
  };
 
  protected final UpdateModelCommand updateValueCommand = new UpdateModelCommand() {

    public void execute(FacesContext context) {
      if (isLocalValueSet() && valueHolder != null) {
        ValueBinding vb = getValueBinding("value");
        if (vb != null) {
          vb.setValue(context, valueHolder.value);
          setValue(null);
          setLocalValueSet(false);
        }
      }
    }
   
  };
 
  /**
   * <p>Perform the following algorithm to update the model dataMap
   * associated with this {@link UIInput}, if any, as appropriate.</p>
   * <ul>
   * <li>If the <code>valid</code> property of this component is
   *     <code>false</code>, take no further action.</li>
   * <li>If the <code>localValueSet</code> property of this component is
   *     <code>false</code>, take no further action.</li>
   * <li>If no {@link ValueBinding} for <code>value</code> exists,
   *     take no further action.</li>
   * <li>Call <code>setValue()</code> method of the {@link ValueBinding}
   *      to update the value that the {@link ValueBinding} points at.</li>
   * <li>If the <code>setValue()</code> method returns successfully:
   *     <ul>
   *     <li>Clear the local value of this {@link UIInput}.</li>
   *     <li>Set the <code>localValueSet</code> property of this
   *         {@link UIInput} to false.</li>
   *     </ul></li>
   * <li>If the <code>setValue()</code> method call fails:
   *     <ul>
   *     <li>Enqueue an error message by calling <code>addMessage()</code>
   *         on the specified {@link FacesContext} instance.</li>
   *     <li>Set the <code>valid</code> property of this {@link UIInput}
   *         to <code>false</code>.</li>
   *     </ul></li>
   * </ul>
   *
   * @param context {@link FacesContext} for the request we are processing
   *
   * @exception NullPointerException if <code>context</code>
   *  is <code>null</code>
   */
  public void updateModel(FacesContext context) {

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

    if (!isValid()) {
      return;
    }

    if (valueHolder != null) {
      updateModel(context, updateValueCommand);
      updateModel(context, updateSelectionCommand);
      updateModel(context, updateActiveItemCommand);
    }
  }


  // ------------------------------------------------------ Validation Methods


  /**
   * <p>Perform the following algorithm to validate the local value of
   * this {@link UIInput}.</p>
   * <ul>
   * <li>Retrieve the submitted value with <code>getSubmittedValue()</code>.
   *   If this returns null, exit without further processing.  (This
   *   indicates that no value was submitted for this component.)</li>
   *
   * <li> Convert the submitted value into a "local value" of the
   * appropriate dataMap type by calling {@link #getConvertedValue}.</li>
   *
   * <li>Validate the property by calling {@link #validateValue}.</li>
   *
   * <li>If the <code>valid</code> property of this component is still
   *     <code>true</code>, retrieve the previous value of the component
   *     (with <code>getValue()</code>), store the new local value using
   *     <code>setValue()</code>, 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.</li>
   * </ul>
   *
   * <p>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
   * <code>super.validate()</code> method to perform the standard
   * processing described above.</p>
   *
   * @param context The {@link FacesContext} for the current request
   *
   * @exception NullPointerException if <code>context</code>
   *  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
   
//    http://jira.jboss.com/jira/browse/RF-3852
//    if (submittedValueHolder == null) {
//      return;
//    }

    Object previousValue = getValue();
    Object newValue = null;

    try {
      if (previousValue == null) {
        previousValue = Collections.EMPTY_LIST;
      }

      try {
        final ArrayList list = new ArrayList(getRowCount());
       
        Object key = getRowKey();
        captureOrigValue(context);
       
        walk(context, new DataVisitor() {
          public void process(FacesContext context, Object rowKey,
              Object argument) throws IOException {

            setRowKey(context, rowKey);
            list.add(getRowData());
          }

        }, null);

        setRowKey(key);
        restoreOrigValue(context);

        newValue = createContainer(list, previousValue);
      } catch (IOException e) {
        throw new ConverterException(e.getLocalizedMessage(), e);
      }
    }
    catch (ConverterException ce) {
      Object submittedValue = submittedValueHolder;
      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()) {
      setSelection(submittedValueHolder.selection);

      setActiveItem(submittedValueHolder.activeItem);
     
      setValue(newValue);

      if (compareValues(previousValue, newValue)) {
        queueEvent(new ValueChangeEvent(this, previousValue, newValue));
      }

      this.submittedValueHolder.setNull();
    }
  }

  protected void resetDataModel() {
    super.resetDataModel();

    if (this.submittedValueHolder != null) {
      this.submittedValueHolder.resetDataModel();
    }
  }

  public ItemState getItemState() {
    if (submittedValueHolder != null && !submittedValueHolder.isNull()) {
      return new ModelItemState(submittedValueHolder.selection,
          submittedValueHolder.activeItem);
    } else {
      return new ModelItemState(getSelection(), getActiveItem());
    }
  }

  public abstract String getControlsType();
  public abstract void setControlsType(String type);

  public Set getSelection() {
    if (valueHolder != null && valueHolder.selection != null) {
      return valueHolder.selection;
    } else {
      ValueBinding vb = getValueBinding("selection");
      if (vb != null) {
        return (Set) vb.getValue(FacesContext.getCurrentInstance());
      }
    }
   
    return null;
  }
 
  public void setSelection(Set selection) {
    createValueHolder();
    valueHolder.selection = selection;
    valueHolder.selectionSet = true;
  }
 
  public Object getActiveItem() {
    if (valueHolder != null && valueHolder.activeItem != null) {
      return valueHolder.activeItem;
    } else {
      ValueBinding vb = getValueBinding("activeItem");
      if (vb != null) {
        return vb.getValue(FacesContext.getCurrentInstance());
      }
    }
   
    return null;
  }
 
  public void setActiveItem(Object activeItem) {
    createValueHolder();
    valueHolder.activeItem = activeItem;
    valueHolder.activeItemSet = true;
  }
 
  private void createValueHolder() {
    if (valueHolder == null) {
      valueHolder = new ValueHolder();
    }
  }

  public void setValue(Object value) {
    if (value instanceof ValueHolder) {
      this.valueHolder = (ValueHolder) value;
    } else {
      createValueHolder();
      valueHolder.value = value;
      setLocalValueSet(true);
    }
  }

  public Object getLocalValue() {
    return valueHolder;
  }
 
  public Object getValue() {
    if (valueHolder != null && valueHolder.value != null) {
      return valueHolder.value;
    }
    ValueBinding ve = getValueBinding("value");
    if (ve != null) {
      return (ve.getValue(getFacesContext()));
    } else {
      return (null);
    }
  }

  public Object saveState(FacesContext faces) {
    Object[] state = new Object[2];
    state[0] = super.saveState(faces);
    if (this.valueHolder != null) {
      state[1] = this.valueHolder.saveState(faces, this);
    }
    return state;
  }
 
  public void restoreState(FacesContext faces, Object object) {
    Object[] state = (Object[]) object;
   
    super.restoreState(faces, state[0]);
   
    if (state[1] != null) {
      this.valueHolder = new ValueHolder();
      this.valueHolder.restoreState(faces, this, state[1]);
    }
  }

}
TOP

Related Classes of org.richfaces.component.UIOrderingList$ValueHolder

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.