Author: nbelaevski
Date: 2007-11-04 23:26:31 -0500 (Sun, 04 Nov 2007)
New Revision: 3744
Added:
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/ArrayUtil.java
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/MessageFactory.java
Modified:
trunk/sandbox/ui/orderingList/src/main/config/component/orderinglist.xml
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/UIOrderingList.java
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/LayoutManager.js
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/OrderingList.js
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/SelectItem.js
trunk/sandbox/ui/orderingList/src/main/templates/org/richfaces/htmlOrderingList.jspx
Log:
orderingList development boost
Modified: trunk/sandbox/ui/orderingList/src/main/config/component/orderinglist.xml
===================================================================
--- trunk/sandbox/ui/orderingList/src/main/config/component/orderinglist.xml 2007-11-05
04:26:21 UTC (rev 3743)
+++ trunk/sandbox/ui/orderingList/src/main/config/component/orderinglist.xml 2007-11-05
04:26:31 UTC (rev 3744)
@@ -132,5 +132,26 @@
</description>
<defaultvalue>true</defaultvalue>
</property>
+
+ <property hidden="true" el="false">
+ <name>submittedValue</name>
+ </property>
+ <property hidden="true" el="false">
+ <name>localValueSet</name>
+ </property>
+ <property hidden="true" el="false">
+ <name>valid</name>
+ </property>
+ <property elonly="true">
+ <name>validator</name>
+ <classname>javax.faces.el.MethodBinding</classname>
+ <methodargs>javax.faces.event.ValueChangeEvent</methodargs>
+ </property>
</component>
+
+ <listener>
+ <componentclass>javax.faces.component.EditableValueHolder</componentclass>
+ <eventclass>javax.faces.event.ValueChangeEvent</eventclass>
+ <name>valueChangeListener</name>
+ </listener>
</components>
Added: trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/ArrayUtil.java
===================================================================
--- trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/ArrayUtil.java
(rev 0)
+++
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/ArrayUtil.java 2007-11-05
04:26:31 UTC (rev 3744)
@@ -0,0 +1,83 @@
+/**
+ *
+ */
+package org.richfaces.component;
+
+
+/**
+ * @author Nick Belaevski
+ * mailto:nbelaevski@exadel.com
+ * created 05.11.2007
+ *
+ * @since 3.2
+ */
+class ArrayUtil {
+
+ final static void copy(Object out, Object in, int[] indexes) {
+ if (in instanceof int[]) {
+ copy((int[])out, (int[])in, indexes);
+ } else if (in instanceof short[]) {
+ copy((short[])out, (short[])in, indexes);
+ } else if (in instanceof byte[]) {
+ copy((byte[])out, (byte[])in, indexes);
+ } else if (in instanceof boolean[]) {
+ copy((boolean[])out, (boolean[])in, indexes);
+ } else if (in instanceof char[]) {
+ copy((char[])out, (char[])in, indexes);
+ } else if (in instanceof float[]) {
+ copy((float[])out, (float[])in, indexes);
+ } else if (in instanceof double[]) {
+ copy((double[])out, (double[])in, indexes);
+ } else if (in instanceof long[]) {
+ copy((long[])out, (long[])in, indexes);
+ } else {
+ copy((Object[])out, (Object[])in, indexes);
+ }
+ }
+
+ final static void copy(Object[] out, Object[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(int[] out, int[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(short[] out, short[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(byte[] out, byte[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(boolean[] out, boolean[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(char[] out, char[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(float[] out, float[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(double[] out, double[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+ final static void copy(long[] out, long[] in, int[] indexes) {
+ for (int i = 0; i < indexes.length; i++) {
+ out[i] = in[indexes[i]];
+ }
+ }
+}
Added:
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/MessageFactory.java
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/MessageFactory.java
(rev 0)
+++
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/MessageFactory.java 2007-11-05
04:26:31 UTC (rev 3744)
@@ -0,0 +1,22 @@
+/**
+ *
+ */
+package org.richfaces.component;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Nick Belaevski
+ * mailto:nbelaevski@exadel.com
+ * created 05.11.2007
+ * @since 3.2
+ */
+public class MessageFactory {
+
+ public static FacesMessage getMessage(FacesContext context,
+ String conversionMessageId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
Modified:
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/UIOrderingList.java
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/UIOrderingList.java 2007-11-05
04:26:21 UTC (rev 3743)
+++
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/component/UIOrderingList.java 2007-11-05
04:26:31 UTC (rev 3744)
@@ -1,9 +1,34 @@
package org.richfaces.component;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.faces.FacesException;
+import javax.faces.application.Application;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIColumn;
+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.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.ValueChangeEvent;
+import javax.faces.event.ValueChangeListener;
+import javax.faces.model.DataModel;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
import org.ajax4jsf.component.UIDataAdaptor;
import org.ajax4jsf.model.DataComponentState;
@@ -14,33 +39,117 @@
import org.apache.commons.collections.iterators.EmptyIterator;
import org.apache.commons.collections.iterators.FilterIterator;
-public abstract class UIOrderingList extends UIDataAdaptor {
+public abstract class UIOrderingList extends UIDataAdaptor implements EditableValueHolder
{
- private List synchronizedList;
-
- private List selectedItems;
-
- private Object activeItem;
-
public static final Predicate isColumn = new ColumnPredicate();
-
+
private static final class ColumnPredicate implements Predicate {
public boolean evaluate(Object input) {
return (input instanceof UIColumn || input instanceof Column);
}
}
-
- @Override
+
protected DataComponentState createComponentState() {
return new RepeatState();
}
- @Override
protected ExtendedDataModel createDataModel() {
- return new SequenceDataModel(super.getDataModel());
+ try {
+ insideCreateDataModel = true;
+
+ return new SequenceDataModel(super.getDataModel());
+ } finally {
+ insideCreateDataModel = false;
+ }
}
- @Override
+ private boolean insideCreateDataModel;
+
+ private DataModel getPermutatedDataModel(final DataModel dataModel) {
+
+ if (submittedValue == null) {
+ return dataModel;
+ } else {
+ return new DataModel() {
+
+ private int rowIndex = -1;
+ private int[] indexes;
+
+ {
+ String[] valueOrder = ((String) submittedValue).split(",");
+ for (int i = 0; i < valueOrder.length; i++) {
+ String[] currentOrder = valueOrder[i].split("d+");
+
+ try {
+ indexes[i] = Integer.valueOf(currentOrder[0]).intValue();
+ } catch (NumberFormatException e) {
+ // TODO: handle exception
+ }
+
+// Object currentItem = oldValues.get(itemIndex.intValue());
+// synchronizedList.add(currentItem);
+//
+// if (currentOrder.length > 1) {
+// Iterator it = Arrays.asList(currentOrder[1].toCharArray()).iterator();
+// while (it.hasNext()) {
+// Character marker = (Character) it.next();
+// if (ACTIVITY_MARKER.equals(marker)) {
+// activeItem = currentItem;
+// } else if (SELECTION_MARKER.equals(marker)) {
+// selectedItems.add(currentItem);
+// }
+// }
+// }
+ }
+ }
+
+ @Override
+ public int getRowCount() {
+ return dataModel.getRowCount();
+ }
+
+ @Override
+ public Object getRowData() {
+ return dataModel.getRowData();
+ }
+
+ @Override
+ public int getRowIndex() {
+ return rowIndex;
+ }
+
+ @Override
+ public Object getWrappedData() {
+ return dataModel.getWrappedData();
+ }
+
+ @Override
+ public boolean isRowAvailable() {
+ return dataModel.isRowAvailable();
+ }
+
+ @Override
+ public void setRowIndex(int rowIndex) {
+ if (rowIndex < -1) {
+ throw new IllegalArgumentException();
+ }
+
+ if (rowIndex < indexes.length) {
+ dataModel.setRowIndex(indexes[rowIndex]);
+ }
+
+ this.rowIndex = rowIndex;
+ }
+
+ @Override
+ public void setWrappedData(Object data) {
+ dataModel.setWrappedData(data);
+ }
+
+ };
+ }
+ }
+
protected Iterator dataChildren() {
if (getChildCount() != 0) {
return getChildren().iterator();
@@ -49,7 +158,6 @@
}
}
- @Override
protected Iterator fixedChildren() {
if (getFacetCount() != 0) {
return getFacets().values().iterator();
@@ -58,31 +166,699 @@
}
}
- public List getSynchronizedList() {
- return synchronizedList;
+ public Iterator columns() {
+ return new FilterIterator(getChildren().iterator(), isColumn);
}
- public void setSynchronizedList(List synchronizedList) {
- this.synchronizedList = synchronizedList;
+ private List validators = null;
+ private MethodBinding validator;
+
+ private Object value;
+ private boolean localValueSet;
+
+ private Object submittedValue;
+
+ 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]);
+ value = state[3];
+ localValueSet = ((Boolean) state[4]).booleanValue();
}
- public List getSelectedItems() {
- return selectedItems;
+ public Object saveState(FacesContext faces) {
+ Object[] state = new Object[5];
+ state[0] = super.saveState(faces);
+ state[1] = saveAttachedState(faces, validators);
+ state[2] = saveAttachedState(faces, validator);
+ state[3] = value;
+ state[4] = localValueSet ? Boolean.TRUE : Boolean.FALSE;
+
+ return state;
}
- public void setSelectedItems(List selectedItems) {
- this.selectedItems = selectedItems;
+ public void addValidator(Validator validator) {
+ if (validator == null) {
+ throw new NullPointerException();
+ }
+
+ if (validators == null) {
+ validators = new ArrayList();
+ }
+
+ validators.add(validator);
}
- public Object getActiveItem() {
- return activeItem;
+ public void addValueChangeListener(ValueChangeListener listener) {
+ addFacesListener(listener);
}
- public void setActiveItem(Object activeItem) {
- this.activeItem = activeItem;
+ public MethodBinding getValidator() {
+ return validator;
}
+
+ public Validator[] getValidators() {
+ if (validators == null) {
+ return new Validator[0];
+ } else {
+ return (Validator[]) validators.toArray(new Validator[validators.size()]);
+ }
+ }
+
+ public abstract MethodBinding getValueChangeListener();
+
+ public ValueChangeListener[] getValueChangeListeners() {
+ return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class);
+ }
+
+ public abstract boolean isImmediate();
+
+ public boolean isLocalValueSet() {
+ return localValueSet;
+ }
+
+ public void setLocalValueSet(boolean localValueSet) {
+ this.localValueSet = localValueSet;
+ }
+
+ public abstract boolean isRequired();
+
+ public abstract boolean isValid();
+
+ public void removeValidator(Validator validator) {
+ if (validators != null) {
+ validators.remove(validator);
+ }
+ }
+
+ public void removeValueChangeListener(ValueChangeListener listener) {
+ removeFacesListener(listener);
+ }
- public Iterator columns() {
- return new FilterIterator(getChildren().iterator(), isColumn);
+ public Object getSubmittedValue() {
+ return submittedValue;
}
+
+ public void setSubmittedValue(Object submittedValue) {
+ this.submittedValue = submittedValue;
+ }
+
+ public abstract void setImmediate(boolean immediate);
+
+ public abstract void setRequired(boolean required);
+
+ public abstract void setValid(boolean valid);
+
+ public void setValidator(MethodBinding validatorBinding) {
+ this.validator = validatorBinding;
+ }
+
+ public abstract void setValueChangeListener(MethodBinding valueChangeMethod);
+
+ public abstract Converter getConverter();
+
+ public abstract void setConverter(Converter converter);
+
+
+ public Object getLocalValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ setLocalValueSet(true);
+ }
+
+ private Object getComponentValue() {
+ if (this.value != null) {
+ return (this.value);
+ }
+ ValueBinding ve = getValueBinding("value");
+ if (ve != null) {
+ return (ve.getValue(getFacesContext()));
+ } else {
+ return (null);
+ }
+ }
+
+ public Object getValue() {
+ if (insideCreateDataModel) {
+ if (submittedValue != null) {
+ return getConvertedValue();
+ }
+ }
+
+ return getComponentValue();
+ }
+
+
+ /**
+ * <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);
+ }
+ }
+
+ /**
+ * <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>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();
+ }
+ }
+
+ /**
+ * @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>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 });
+ }
+ }
+
+ }
+
+
+ /**
+ * <p>Perform the following algorithm to update the model data
+ * 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() || !isLocalValueSet()) {
+ return;
+ }
+
+ ValueBinding vb = getValueBinding("value");
+ if (vb != null) {
+ try {
+ vb.setValue(context, getLocalValue());
+ setValue(null);
+ setLocalValueSet(false);
+ return;
+ } catch (EvaluationException e) {
+ String messageStr = e.getMessage();
+ FacesMessage message = null;
+ if (null == messageStr) {
+ message =
+ MessageFactory.getMessage(context, UIInput.CONVERSION_MESSAGE_ID);
+ }
+ else {
+ message = new FacesMessage(messageStr);
+ }
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+ context.addMessage(getClientId(context), message);
+ setValid(false);
+ }
+ catch (FacesException e) {
+ FacesMessage message =
+ MessageFactory.getMessage(context, UIInput.CONVERSION_MESSAGE_ID);
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+ context.addMessage(getClientId(context), message);
+ setValid(false);
+ } catch (IllegalArgumentException e) {
+ FacesMessage message =
+ MessageFactory.getMessage(context, UIInput.CONVERSION_MESSAGE_ID);
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+ context.addMessage(getClientId(context), message);
+ setValid(false);
+ } catch (Exception e) {
+ FacesMessage message =
+ MessageFactory.getMessage(context, UIInput.CONVERSION_MESSAGE_ID);
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+ context.addMessage(getClientId(context), message);
+ setValid(false);
+ }
+ }
+ }
+
+
+ // ------------------------------------------------------ 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 data 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
+ Object submittedValue = getSubmittedValue();
+ if (submittedValue == null) {
+ return;
+ }
+
+ Object newValue = null;
+
+ try {
+ newValue = getConvertedValue();
+ }
+ 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));
+ }
+ }
+
+ }
+
+ protected Object getConvertedValue() throws ConverterException {
+ if (submittedValue instanceof String) {
+ Object componentValue = getComponentValue();
+ if (componentValue == null) {
+ return Collections.EMPTY_LIST;
+ }
+
+ String[] valueOrder = ((String) submittedValue).split(",");
+ int[] indexes = new int[valueOrder.length];
+ for (int i = 0; i < valueOrder.length; i++) {
+ Matcher matcher =
Pattern.compile("(\\d+)(s)?(a)?").matcher(valueOrder[i]);
+ matcher.matches();
+
+ try {
+ indexes[i] = Integer.valueOf(matcher.group(1)).intValue();
+ } catch (NumberFormatException e) {
+ // TODO: handle exception
+ }
+
+// Object currentItem = oldValues.get(itemIndex.intValue());
+// synchronizedList.add(currentItem);
+//
+// if (currentOrder.length > 1) {
+// Iterator it = Arrays.asList(currentOrder[1].toCharArray()).iterator();
+// while (it.hasNext()) {
+// Character marker = (Character) it.next();
+// if (ACTIVITY_MARKER.equals(marker)) {
+// activeItem = currentItem;
+// } else if (SELECTION_MARKER.equals(marker)) {
+// selectedItems.add(currentItem);
+// }
+// }
+// }
+ }
+
+ if (componentValue instanceof List) {
+ List list = (List) componentValue;
+ ArrayList arrayList = new ArrayList(list.size());
+ for (int i = 0; i < indexes.length; i++) {
+ int j = indexes[i];
+ arrayList.add(list.get(j));
+ }
+ submittedValue = arrayList;
+ } else {
+ submittedValue = Array.newInstance(componentValue.getClass().getComponentType(),
+ Array.getLength(componentValue));
+ ArrayUtil.copy(submittedValue,
+ componentValue, indexes);
+ }
+ }
+
+ return submittedValue;
+ }
+
+ /**
+ *
+ * <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) {
+ // If our value is valid, enforce the required property if present
+ if (isValid() && isRequired() && isEmpty(newValue)) {
+ FacesMessage message =
+ MessageFactory.getMessage(context, UIInput.REQUIRED_MESSAGE_ID);
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+ 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) {
+ Iterator validators = this.validators.iterator();
+ while (validators.hasNext()) {
+ Validator validator = (Validator) validators.next();
+ 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);
+ }
+ }
+ }
+ }
+ 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>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 {
+ 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 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);
+ }
+
+
+ private Converter getConverterWithType(FacesContext context) {
+ Converter converter = getConverter();
+ if (converter != null) {
+ return converter;
+ }
+
+ ValueBinding valueBinding = getValueBinding("value");
+ if (valueBinding == null) {
+ return null;
+ }
+
+ Class converterType = valueBinding.getType(context);
+ // 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 = ce.getFacesMessage();
+ if (message == null) {
+ message = MessageFactory.getMessage(context,
+ UIInput.CONVERSION_MESSAGE_ID);
+ if (message.getDetail() == null) {
+ message.setDetail(ce.getMessage());
+ }
+ }
+
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+ context.addMessage(getClientId(context), message);
+ }
}
Modified:
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java 2007-11-05
04:26:21 UTC (rev 3743)
+++
trunk/sandbox/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java 2007-11-05
04:26:31 UTC (rev 3744)
@@ -21,8 +21,6 @@
public abstract class OrderingListRendererBase extends AbstractRowsRenderer {
- private final static String VALUE_ORDER_ID_PREFIX = "valueKeeper";
-
private final static Character ACTIVITY_MARKER = 'a';
private final static Character SELECTION_MARKER = 's';
@@ -109,7 +107,6 @@
}
}
- @Override
public void encodeOneRow(FacesContext context, TableHolder holder)
throws IOException {
@@ -145,12 +142,10 @@
Map requestParameterMap = context.getExternalContext()
.getRequestParameterMap();
- String valueOrder = (String)
requestParameterMap.get(clientId.concat(VALUE_ORDER_ID_PREFIX));
+ String valueOrder = (String) requestParameterMap.get(clientId);
- if (valueOrder != null) {
- String[] valueOrderAr = valueOrder.split(ITEM_SEPARATOR);
- List oldValues = (List) orderingList.getValue();
- valuesSynchronization(valueOrderAr, oldValues);
+ if (valueOrder != null && valueOrder.length() != 0) {
+ orderingList.setSubmittedValue(valueOrder);
}
}
Modified:
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/LayoutManager.js
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/LayoutManager.js 2007-11-05
04:26:21 UTC (rev 3743)
+++
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/LayoutManager.js 2007-11-05
04:26:31 UTC (rev 3744)
@@ -20,6 +20,8 @@
LayoutManager.prototype.widthSynchronization = function() {
var contentCells = this.contentTable.tBodies[0].rows[0].cells;
+ if (!this.headerTable || !this.headerTable.tHead)
+ return ;
var headerCells = this.headerTable.tHead.rows[0].cells;
var width;
for (var i = 0; i < contentCells.length; i++) {
Modified:
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/OrderingList.js
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/OrderingList.js 2007-11-05
04:26:21 UTC (rev 3743)
+++
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/OrderingList.js 2007-11-05
04:26:31 UTC (rev 3744)
@@ -123,6 +123,11 @@
}
}
+ this.shuttleItems = new Array();
+ for (var i = 0; i < rows.length; i++) {
+ this.shuttleItems.push(rows[i].item);
+ }
+
this.saveState();
}
}
Modified:
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/SelectItem.js
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/SelectItem.js 2007-11-05
04:26:21 UTC (rev 3743)
+++
trunk/sandbox/ui/orderingList/src/main/resources/org/richfaces/renderkit/html/scripts/SelectItem.js 2007-11-05
04:26:31 UTC (rev 3744)
@@ -1,6 +1,7 @@
SelectItem = function(label, id, selected, node) {
this._label = label;
this._node = node;
+ this._node.item = this;
this._id = id;
this._selected = selected;
}
\ No newline at end of file
Modified:
trunk/sandbox/ui/orderingList/src/main/templates/org/richfaces/htmlOrderingList.jspx
===================================================================
---
trunk/sandbox/ui/orderingList/src/main/templates/org/richfaces/htmlOrderingList.jspx 2007-11-05
04:26:21 UTC (rev 3743)
+++
trunk/sandbox/ui/orderingList/src/main/templates/org/richfaces/htmlOrderingList.jspx 2007-11-05
04:26:31 UTC (rev 3744)
@@ -32,7 +32,7 @@
<div id="#{clientId}"
onclick="Shuttle.setFocus('#{clientId}focusKeeper')">
<input id="#{clientId}focusKeeper" type="button"
value="" style="position: absolute; left: -32767;"
name="focusKeeper"/>
- <input id="#{clientId}valueKeeper" type="hidden"
name="valueKeeper" value=""/>
+ <input id="#{clientId}valueKeeper" type="hidden"
name="#{clientId}" value=""/>
<table id="#{clientId}table" cellpadding="0"
cellspacing="0" class="ol_body">
<tr>