You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/11/10 03:11:47 UTC
svn commit: r1033329 [2/2] - in /myfaces/commons/branches/jsf_20:
myfaces-commons-converters/src/main/java/org/apache/myfaces/commons/converter/
myfaces-commons-converters/src/main/resources/META-INF/
myfaces-commons-validators/src/main/java/org/apache...
Added: myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/java/org/apache/myfaces/commons/validator/_DeltaStateHelper.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/java/org/apache/myfaces/commons/validator/_DeltaStateHelper.java?rev=1033329&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/java/org/apache/myfaces/commons/validator/_DeltaStateHelper.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/java/org/apache/myfaces/commons/validator/_DeltaStateHelper.java Wed Nov 10 02:11:46 2010
@@ -0,0 +1,827 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.validator;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.el.ValueExpression;
+import javax.faces.component.StateHelper;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+
+/**
+ * A delta enabled state holder implementing the StateHolder Interface.
+ * <p>
+ * Components implementing the PartalStateHolder interface have an initial state
+ * and delta states, the initial state is the one holding all root values
+ * and deltas store differences to the initial states
+ * </p>
+ * <p>
+ * For components not implementing partial state saving only the initial states are
+ * of importance, everything is stored and restored continously there
+ * </p>
+ * <p>
+ * The state helper seems to have three internal storage mechanisms:
+ * one being a list which stores plain values,
+ * one being a key value pair which stores key values in maps
+ * add serves the plain list type while put serves the
+ * key value type,
+ * the third is the value which has to be stored plainly as is!
+ * </p>
+ * In other words, this map can be seen as a composite map. It has two maps:
+ * initial state map and delta map.
+ * <p>
+ * If delta map is used (method component.initialStateMarked() ),
+ * base or initial state map cannot be changed, since all changes
+ * should be tracked on delta map.
+ * </p>
+ * <p>
+ * The intention of this class is just hold property values
+ * and do a clean separation between initial state and delta.
+ * </p>
+ * <p>
+ * The code from this class comes from a refactor of
+ * org.apache.myfaces.trinidad.bean.util.PropertyHashMap
+ * </p>
+ * <p>
+ * The context from this class comes and that should be taken into account
+ * is this:
+ * </p>
+ * <p>
+ * First request:
+ * </p>
+ * <ul>
+ * <li> A new template is created (using
+ * javax.faces.view.ViewDeclarationLanguage.buildView method)
+ * and component.markInitialState is called from its related TagHandler classes
+ * (see javax.faces.view.facelets.ComponentHandler ).
+ * When this method is executed, the component tree was populated from the values
+ * set in the facelet abstract syntax tree (or in other words composition of
+ * facelets templates). </li>
+ * <li> From this point all updates on the variables are considered "delta". </li>
+ * <li> SaveState, if initialStateMarked is true, only delta is saved. </li>
+ * </ul>
+ * <p>
+ * Second request (and next ones)
+ * </p>
+ * <ul>
+ * <li> A new template is created and component.markInitialState is called from
+ * its related TagHandler classes again. In this way, components like c:forEach
+ * or c:if, that add or remove components could notify about this and handle
+ * them properly (see javax.faces.view.StateManagementStrategy). Note that a
+ * component restored using this method is no different as the same component
+ * at the first request at the same time. </li>
+ * <li> A call for restoreState is done, passing the delta as object value. If no
+ * delta, the state is complete and no call is triggered. </li>
+ * <li> Lifecycle occur, changing the necessary stuff. </li>
+ * <li> SaveState, if initialStateMarked is true, only delta is saved. </li>
+ * </ul>
+ * <p>
+ * From the previous analysis, the following conclusions arise:
+ * <ul>
+ * <li>This class only needs to keep track of delta changes, so when
+ * restoreState/saveState is called, the right objects are passed.</li>
+ * <li>UIComponent.clearInitialState is used to reset the partial
+ * state holder to a non delta state, so the state to be saved by
+ * saveState is no longer a delta instead is a full state. If a call
+ * to clearInitialState occur it is not expected a call for
+ * UIComponent.markInitialState occur on the current request.</li>
+ * <li>The state is handled in the same way on UIData, so components
+ * inside UIData share its state on all rows. There is no way to save
+ * delta per row.</li>
+ * <li>The map backed by method put(Serializable,String,Object) is
+ * a replacement of UIComponentBase.attributesMap and UIComponent.bindings map.
+ * Note that on jsf 1.2, instances saved on attributesMap should not be
+ * StateHolder, but on jsf 2.0 it is possible to have it. PartialStateHolder
+ * instances are not handled in this map, or in other words delta state is not
+ * handled in this classes (markInitialState and clearInitialState is not propagated).</li>
+ * <li>The list backed by method add(Serializable,Object) should be (is not) a
+ * replacement of UIComponentBase.facesListeners, but note that StateHelper
+ * does not implement PartialStateHolder, and facesListener could have instances
+ * of that class that needs to be notified when UIComponent.markInitialState or
+ * UIComponent.clearInitialState is called, or in other words facesListeners
+ * should deal with PartialStateHolder instances.</li>
+ * <li>The list backed by method add(Serializable,Object) is
+ * a replacement of UIViewRoot.phaseListeners list. Note that instances of
+ * PhaseListener are not expected to implement StateHolder or PartialStateHolder.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * NOTE: The current implementation of StateHelper on RI does not handle
+ * stateHolder values internally. To prevent problems when developers create
+ * custom components we should do this too. But anyway, the code that
+ * handle this case should be let here as comment, if some day this feature
+ * is provided. Note than stateHolder aware properties like converter,
+ * validator or listeners should deal with StateHolder or PartialStateHolder
+ * on component classes.
+ *
+ * </p>
+ *
+ * @author Werner Punz
+ * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
+ * @version $Rev: 980927 $ $Date: 2010-07-30 14:05:55 -0500 (Vie, 30 Jul 2010) $
+ */
+class _DeltaStateHelper implements StateHelper
+{
+
+ /**
+ * We need to hold a component instance because:
+ *
+ * - The component is the one who knows if we are on initial or delta mode
+ * - eval assume calls to component.ValueExpression
+ */
+ private ValidatorBase _component;
+
+ /**
+ * This map holds the full current state
+ */
+ private Map<Serializable, Object> _fullState;
+
+ /**
+ * This map only keep track of delta changes to be saved
+ */
+ private Map<Serializable, Object> _deltas;
+
+ /**
+ * This map keep track of StateHolder keys, to be saved when
+ * saveState is called.
+ */
+ //private Set<Serializable> _stateHolderKeys;
+
+ private boolean _transient = false;
+
+ public _DeltaStateHelper(ValidatorBase component)
+ {
+ super();
+ this._component = component;
+ _fullState = new HashMap<Serializable, Object>();
+ _deltas = null;
+ //_stateHolderKeys = new HashSet<Serializable>();
+ }
+
+ /**
+ * Used to create delta map on demand
+ *
+ * @return
+ */
+ private boolean _createDeltas()
+ {
+ if (isInitialStateMarked())
+ {
+ if (_deltas == null)
+ {
+ _deltas = new HashMap<Serializable, Object>(2);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean isInitialStateMarked()
+ {
+ return _component.initialStateMarked();
+ }
+
+ public void add(Serializable key, Object value)
+ {
+ if (_createDeltas())
+ {
+ //Track delta case
+ Map<Object, Boolean> deltaListMapValues = (Map<Object, Boolean>) _deltas
+ .get(key);
+ if (deltaListMapValues == null)
+ {
+ deltaListMapValues = new InternalDeltaListMap<Object, Boolean>(
+ 3);
+ _deltas.put(key, deltaListMapValues);
+ }
+ deltaListMapValues.put(value, Boolean.TRUE);
+ }
+
+ //Handle change on full map
+ List<Object> fullListValues = (List<Object>) _fullState.get(key);
+ if (fullListValues == null)
+ {
+ fullListValues = new InternalList<Object>(3);
+ _fullState.put(key, fullListValues);
+ }
+ fullListValues.add(value);
+ }
+
+ public Object eval(Serializable key)
+ {
+ Object returnValue = _fullState.get(key);
+ if (returnValue != null)
+ {
+ return returnValue;
+ }
+ ValueExpression expression = _component.getValueExpression(key
+ .toString());
+ if (expression != null)
+ {
+ return expression.getValue(_component.getFacesContext()
+ .getELContext());
+ }
+ return null;
+ }
+
+ public Object eval(Serializable key, Object defaultValue)
+ {
+ Object returnValue = _fullState.get(key);
+ if (returnValue != null)
+ {
+ return returnValue;
+ }
+ ValueExpression expression = _component.getValueExpression(key
+ .toString());
+ if (expression != null)
+ {
+ return expression.getValue(_component.getFacesContext()
+ .getELContext());
+ }
+ return defaultValue;
+ }
+
+ public Object get(Serializable key)
+ {
+ return _fullState.get(key);
+ }
+
+ public Object put(Serializable key, Object value)
+ {
+ Object returnValue = null;
+ if (_createDeltas())
+ {
+ if (_deltas.containsKey(key))
+ {
+ returnValue = _deltas.put(key, value);
+ _fullState.put(key, value);
+ }
+ else if (value == null && !_fullState.containsKey(key))
+ {
+ returnValue = null;
+ }
+ else
+ {
+ _deltas.put(key, value);
+ returnValue = _fullState.put(key, value);
+ }
+ }
+ else
+ {
+ /*
+ if (value instanceof StateHolder)
+ {
+ _stateHolderKeys.add(key);
+ }
+ */
+ returnValue = _fullState.put(key, value);
+ }
+ return returnValue;
+ }
+
+ public Object put(Serializable key, String mapKey, Object value)
+ {
+ boolean returnSet = false;
+ Object returnValue = null;
+ if (_createDeltas())
+ {
+ //Track delta case
+ Map<String, Object> mapValues = (Map<String, Object>) _deltas
+ .get(key);
+ if (mapValues == null)
+ {
+ mapValues = new InternalMap<String, Object>();
+ _deltas.put(key, mapValues);
+ }
+ if (mapValues.containsKey(mapKey))
+ {
+ returnValue = mapValues.put(mapKey, value);
+ returnSet = true;
+ }
+ else
+ {
+ mapValues.put(mapKey, value);
+ }
+ }
+
+ //Handle change on full map
+ Map<String, Object> mapValues = (Map<String, Object>) _fullState
+ .get(key);
+ if (mapValues == null)
+ {
+ mapValues = new InternalMap<String, Object>();
+ _fullState.put(key, mapValues);
+ }
+ if (returnSet)
+ {
+ mapValues.put(mapKey, value);
+ }
+ else
+ {
+ returnValue = mapValues.put(mapKey, value);
+ }
+ return returnValue;
+ }
+
+ public Object remove(Serializable key)
+ {
+ Object returnValue = null;
+ if (_createDeltas())
+ {
+ if (_deltas.containsKey(key))
+ {
+ // Keep track of the removed values using key/null pair on the delta map
+ returnValue = _deltas.put(key, null);
+ _fullState.remove(key);
+ }
+ else
+ {
+ // Keep track of the removed values using key/null pair on the delta map
+ _deltas.put(key, null);
+ returnValue = _fullState.remove(key);
+ }
+ }
+ else
+ {
+ returnValue = _fullState.remove(key);
+ }
+ return returnValue;
+ }
+
+ public Object remove(Serializable key, Object valueOrKey)
+ {
+ // Comment by lu4242 : The spec javadoc says if it is a Collection
+ // or Map deal with it. But the intention of this method is work
+ // with add(?,?) and put(?,?,?), this ones return instances of
+ // InternalMap and InternalList to prevent mixing, so to be
+ // consistent we'll cast to those classes here.
+
+ Object collectionOrMap = _fullState.get(key);
+ Object returnValue = null;
+ if (collectionOrMap instanceof InternalMap)
+ {
+ if (_createDeltas())
+ {
+ returnValue = _removeValueOrKeyFromMap(_deltas, key,
+ valueOrKey, true);
+ _removeValueOrKeyFromMap(_fullState, key, valueOrKey, false);
+ }
+ else
+ {
+ returnValue = _removeValueOrKeyFromMap(_fullState, key,
+ valueOrKey, false);
+ }
+ }
+ else if (collectionOrMap instanceof InternalList)
+ {
+ if (_createDeltas())
+ {
+ returnValue = _removeValueOrKeyFromCollectionDelta(_deltas,
+ key, valueOrKey);
+ _removeValueOrKeyFromCollection(_fullState, key, valueOrKey);
+ }
+ else
+ {
+ returnValue = _removeValueOrKeyFromCollection(_fullState, key,
+ valueOrKey);
+ }
+ }
+ return returnValue;
+ }
+
+ private static Object _removeValueOrKeyFromCollectionDelta(
+ Map<Serializable, Object> stateMap, Serializable key,
+ Object valueOrKey)
+ {
+ Object returnValue = null;
+ Map<Object, Boolean> c = (Map<Object, Boolean>) stateMap.get(key);
+ if (c != null)
+ {
+ if (c.containsKey(valueOrKey))
+ {
+ returnValue = valueOrKey;
+ }
+ c.put(valueOrKey, Boolean.FALSE);
+ }
+ return returnValue;
+ }
+
+ private static Object _removeValueOrKeyFromCollection(
+ Map<Serializable, Object> stateMap, Serializable key,
+ Object valueOrKey)
+ {
+ Object returnValue = null;
+ Collection c = (Collection) stateMap.get(key);
+ if (c != null)
+ {
+ if (c.remove(valueOrKey))
+ {
+ returnValue = valueOrKey;
+ }
+ if (c.isEmpty())
+ {
+ stateMap.remove(key);
+ }
+ }
+ return returnValue;
+ }
+
+ private static Object _removeValueOrKeyFromMap(
+ Map<Serializable, Object> stateMap, Serializable key,
+ Object valueOrKey, boolean delta)
+ {
+ if (valueOrKey == null)
+ {
+ return null;
+ }
+
+ Object returnValue = null;
+ Map<String, Object> map = (Map<String, Object>) stateMap.get(key);
+ if (map != null)
+ {
+ if (delta)
+ {
+ // Keep track of the removed values using key/null pair on the delta map
+ returnValue = map.put((String) valueOrKey, null);
+ }
+ else
+ {
+ returnValue = map.remove(valueOrKey);
+ }
+
+ if (map.isEmpty())
+ {
+ //stateMap.remove(key);
+ stateMap.put(key, null);
+ }
+ }
+ return returnValue;
+ }
+
+ public boolean isTransient()
+ {
+ return _transient;
+ }
+
+ /**
+ * Serializing cod
+ * the serialized data structure consists of key value pairs unless the value itself is an internal array
+ * or a map in case of an internal array or map the value itself is another array with its initial value
+ * myfaces.InternalArray, myfaces.internalMap
+ *
+ * the internal Array is then mapped to another array
+ *
+ * the internal Map again is then mapped to a map with key value pairs
+ *
+ *
+ */
+ public Object saveState(FacesContext context)
+ {
+ Map serializableMap = (isInitialStateMarked()) ? _deltas : _fullState;
+
+ if (serializableMap == null || serializableMap.size() == 0)
+ {
+ return null;
+ }
+
+ /*
+ int stateHolderKeyCount = 0;
+ if (isInitalStateMarked())
+ {
+ for (Iterator<Serializable> it = _stateHolderKeys.iterator(); it.hasNext();)
+ {
+ Serializable key = it.next();
+ if (!_deltas.containsKey(key))
+ {
+ stateHolderKeyCount++;
+ }
+ }
+ }*/
+
+ Map.Entry<Serializable, Object> entry;
+ //entry == key, value, key, value
+ Object[] retArr = new Object[serializableMap.entrySet().size() * 2];
+ //Object[] retArr = new Object[serializableMap.entrySet().size() * 2 + stateHolderKeyCount];
+
+ Iterator<Map.Entry<Serializable, Object>> it = serializableMap
+ .entrySet().iterator();
+ int cnt = 0;
+ while (it.hasNext())
+ {
+ entry = it.next();
+ retArr[cnt] = entry.getKey();
+
+ Object value = entry.getValue();
+
+ // The condition in which the call to saveAttachedState
+ // is to handle List, StateHolder or non Serializable instances.
+ // we check it here, to prevent unnecessary calls.
+ if (value instanceof StateHolder ||
+ value instanceof List ||
+ !(value instanceof Serializable))
+ {
+ Object savedValue = UIComponentBase.saveAttachedState(context,
+ value);
+ retArr[cnt + 1] = savedValue;
+ }
+ else
+ {
+ retArr[cnt + 1] = value;
+ }
+ cnt += 2;
+ }
+
+ /*
+ if (isInitalStateMarked())
+ {
+ for (Iterator<Serializable> it2 = _stateHolderKeys.iterator(); it.hasNext();)
+ {
+ Serializable key = it2.next();
+ if (!_deltas.containsKey(key))
+ {
+ retArr[cnt] = key;
+ Object value = _fullState.get(key);
+ if (value instanceof PartialStateHolder)
+ {
+ //Could contain delta, save it as _AttachedDeltaState
+ PartialStateHolder holder = (PartialStateHolder) value;
+ if (holder.isTransient())
+ {
+ retArr[cnt + 1] = null;
+ }
+ else
+ {
+ retArr[cnt + 1] = new _AttachedDeltaWrapper(value.getClass(), holder.saveState(context));
+ }
+ }
+ else
+ {
+ //Save everything
+ retArr[cnt + 1] = UIComponentBase.saveAttachedState(context, _fullState.get(key));
+ }
+ cnt += 2;
+ }
+ }
+ }
+ */
+ return retArr;
+ }
+
+ public void restoreState(FacesContext context, Object state)
+ {
+ if (state == null)
+ return;
+
+ Object[] serializedState = (Object[]) state;
+
+ if (!isInitialStateMarked() && !_fullState.isEmpty())
+ {
+ _fullState.clear();
+ if(_deltas != null)
+ {
+ _deltas.clear();
+ }
+ }
+
+ for (int cnt = 0; cnt < serializedState.length; cnt += 2)
+ {
+ Serializable key = (Serializable) serializedState[cnt];
+ Object savedValue = UIComponentBase.restoreAttachedState(context,
+ serializedState[cnt + 1]);
+
+ if (isInitialStateMarked())
+ {
+ if (savedValue instanceof InternalDeltaListMap)
+ {
+ for (Map.Entry<Object, Boolean> mapEntry : ((Map<Object, Boolean>) savedValue)
+ .entrySet())
+ {
+ boolean addOrRemove = mapEntry.getValue();
+ if (addOrRemove)
+ {
+ //add
+ this.add(key, mapEntry.getKey());
+ }
+ else
+ {
+ //remove
+ this.remove(key, mapEntry.getKey());
+ }
+ }
+ }
+ else if (savedValue instanceof InternalMap)
+ {
+ for (Map.Entry<String, Object> mapEntry : ((Map<String, Object>) savedValue)
+ .entrySet())
+ {
+ this.put(key, mapEntry.getKey(), mapEntry.getValue());
+ }
+ }
+ /*
+ else if (savedValue instanceof _AttachedDeltaWrapper)
+ {
+ _AttachedStateWrapper wrapper = (_AttachedStateWrapper) savedValue;
+ //Restore delta state
+ ((PartialStateHolder)_fullState.get(key)).restoreState(context, wrapper.getWrappedStateObject());
+ //Add this key as StateHolder key
+ _stateHolderKeys.add(key);
+ }
+ */
+ else
+ {
+ put(key, savedValue);
+ }
+ }
+ else
+ {
+ put(key, savedValue);
+ }
+ }
+ }
+
+ public void setTransient(boolean transientValue)
+ {
+ _transient = transientValue;
+ }
+
+ //We use our own data structures just to make sure
+ //nothing gets mixed up internally
+ static class InternalMap<K, V> extends HashMap<K, V> implements StateHolder
+ {
+ public InternalMap()
+ {
+ super();
+ }
+
+ public InternalMap(int initialCapacity, float loadFactor)
+ {
+ super(initialCapacity, loadFactor);
+ }
+
+ public InternalMap(Map<? extends K, ? extends V> m)
+ {
+ super(m);
+ }
+
+ public InternalMap(int initialSize)
+ {
+ super(initialSize);
+ }
+
+ public boolean isTransient()
+ {
+ return false;
+ }
+
+ public void setTransient(boolean newTransientValue)
+ {
+ // No op
+ }
+
+ public void restoreState(FacesContext context, Object state)
+ {
+ Object[] listAsMap = (Object[]) state;
+ for (int cnt = 0; cnt < listAsMap.length; cnt += 2)
+ {
+ this.put((K) listAsMap[cnt], (V) UIComponentBase
+ .restoreAttachedState(context, listAsMap[cnt + 1]));
+ }
+ }
+
+ public Object saveState(FacesContext context)
+ {
+ int cnt = 0;
+ Object[] mapArr = new Object[this.size() * 2];
+ for (Map.Entry<K, V> entry : this.entrySet())
+ {
+ mapArr[cnt] = entry.getKey();
+ Object value = entry.getValue();
+
+ if (value instanceof StateHolder ||
+ value instanceof List ||
+ !(value instanceof Serializable))
+ {
+ mapArr[cnt + 1] = UIComponentBase.saveAttachedState(context, value);
+ }
+ else
+ {
+ mapArr[cnt + 1] = value;
+ }
+ cnt += 2;
+ }
+ return mapArr;
+ }
+ }
+
+ /**
+ * Map used to keep track of list changes
+ */
+ static class InternalDeltaListMap<K, V> extends InternalMap<K, V>
+ {
+
+ public InternalDeltaListMap()
+ {
+ super();
+ }
+
+ public InternalDeltaListMap(int initialCapacity, float loadFactor)
+ {
+ super(initialCapacity, loadFactor);
+ }
+
+ public InternalDeltaListMap(int initialSize)
+ {
+ super(initialSize);
+ }
+
+ public InternalDeltaListMap(Map<? extends K, ? extends V> m)
+ {
+ super(m);
+ }
+ }
+
+ static class InternalList<T> extends ArrayList<T> implements StateHolder
+ {
+ public InternalList()
+ {
+ super();
+ }
+
+ public InternalList(Collection<? extends T> c)
+ {
+ super(c);
+ }
+
+ public InternalList(int initialSize)
+ {
+ super(initialSize);
+ }
+
+ public boolean isTransient()
+ {
+ return false;
+ }
+
+ public void setTransient(boolean newTransientValue)
+ {
+ }
+
+ public void restoreState(FacesContext context, Object state)
+ {
+ Object[] listAsArr = (Object[]) state;
+ //since all other options would mean dual iteration
+ //we have to do it the hard way
+ for (Object elem : listAsArr)
+ {
+ add((T) UIComponentBase.restoreAttachedState(context, elem));
+ }
+ }
+
+ public Object saveState(FacesContext context)
+ {
+ Object[] values = new Object[size()];
+ for (int i = 0; i < size(); i++)
+ {
+ Object value = get(i);
+
+ if (value instanceof StateHolder ||
+ value instanceof List ||
+ !(value instanceof Serializable))
+ {
+ values[i] = UIComponentBase.saveAttachedState(context, value);
+ }
+ else
+ {
+ values[i] = value;
+ }
+ }
+ return values;
+ }
+ }
+}
Modified: myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/resources/META-INF/validatorClass12.vm
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/resources/META-INF/validatorClass12.vm?rev=1033329&r1=1033328&r2=1033329&view=diff
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/resources/META-INF/validatorClass12.vm (original)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-validators/src/main/resources/META-INF/validatorClass12.vm Wed Nov 10 02:11:46 2010
@@ -176,6 +176,167 @@ public class ${utils.getClassFromFullCla
#end
##
+## -------------------------------
+## writePropertySetStateHelperDeclaration
+## -------------------------------
+##
+#macro (writePropertySetStateHelperDeclaration $property $type $field $defaultValue )
+#if($utils.isPrimitiveClass($type) && !$property.isTagExcluded() && $property.isSetMethod())
+ private boolean ${field}Set;
+
+#end
+#end
+##
+## -------------------------------
+## writePropertyStateHelperDeclaration
+## -------------------------------
+##
+#macro( writePropertyStateHelperDeclaration $property $type $field $defaultValue )
+#if ($property.isPartialStateHolder())
+#if ($property.isLiteralOnly() || $property.isTagExcluded())
+ private $type $field #if($defaultValue) = $defaultValue;#{else};#{end}
+
+#else
+ private $type $field;
+
+#end
+#end
+#writePropertySetStateHelperDeclaration ($property $type $field $defaultValue)
+#end
+##
+## -------------------------------
+## writeLocalPropertyStateHelperGetter
+## -------------------------------
+##
+#macro (writeLocalPropertyStateHelperGetter $property $type $field $defaultValue )
+#if($utils.isPrimitiveClass($type) && !$property.isTagExcluded() && $property.isSetMethod())
+ $property.setMethodScope boolean $utils.getPrefixedPropertyName("isSet", $property.name)()
+ {
+ return ${field}Set;
+ }
+
+#end
+#if($property.isLocalMethod())
+#if("boolean" == $type)
+#set ($methodName = $utils.getPrefixedPropertyName("isLocal", $property.name))
+#else
+#set ($methodName = $utils.getPrefixedPropertyName("getLocal", $property.name))
+#end
+ final $property.localMethodScope $type ${methodName}()
+ {
+#if ($property.isPartialStateHolder())
+ return $field;
+#else
+ return $utils.castIfNecessary($type) getStateHelper().get(PropertyKeys.$field);
+#end
+ }
+
+#end
+#end
+##
+## -------------------------------
+## writePropertyStateHelperGetter
+## -------------------------------
+##
+#macro (writePropertyStateHelperGetter $property $type $field $defaultValue )
+#if ($property.isPartialStateHolder())
+ public $type $utils.getMethodReaderFromProperty($property.name, $type)()
+ {
+#if ($property.isTagExcluded() || $property.isLiteralOnly() || !($validator.isEvaluateELOnExecution()))
+ return $field;
+#else
+#if ($utils.isPrimitiveClass($type))
+ if (${field}Set)
+#else
+ if ($field != null)
+#end
+ {
+ return $field;
+ }
+ ValueExpression vb = getValueExpression("$property.name");
+ if (vb != null)
+ {
+#if ($utils.isPrimitiveClass($type))
+ return ($utils.castIfNecessary($type) vb.getValue(getFacesContext().getELContext())).${type}Value();
+#else
+#set ($pritype = $utils.getPrimitiveType($property.className))
+#if ($utils.isPrimitiveClass($pritype))
+ Object value = vb == null ? null : vb.getValue(getFacesContext().getELContext());
+ if (!(value instanceof $type)){
+ value = ${type}.valueOf(value.toString());
+ }
+ return $utils.castIfNecessary($type) value;
+#else
+ return $utils.castIfNecessary($type) vb.getValue(getFacesContext().getELContext());
+#end
+#end
+ }
+#if ($defaultValue)
+ return $defaultValue;
+#elseif ($utils.isPrimitiveClass($type))
+ return $utils.primitiveDefaultValue($type);
+#else
+ return null;
+#end
+#end
+ }
+
+#else
+ public $type $utils.getMethodReaderFromProperty($property.name, $type)()
+ {
+#if ($property.isLiteralOnly())
+#if ($defaultValue)
+ Object value = getStateHelper().get(PropertyKeys.$field);
+ if (value != null)
+ {
+ return $utils.castIfNecessary($type) value;
+ }
+ return $defaultValue;
+#else
+ return $utils.castIfNecessary($type) getStateHelper().get(PropertyKeys.$field);
+#end
+#else
+#if ($defaultValue)
+ return $utils.castIfNecessary($type) getStateHelper().eval(PropertyKeys.$field, $defaultValue);
+#else
+ return $utils.castIfNecessary($type) getStateHelper().eval(PropertyKeys.$field);
+#end
+#end
+ }
+
+#end
+#end
+##
+## -------------------------------
+## writePropertyStateHelperSetter
+## -------------------------------
+##
+#macro (writePropertyStateHelperSetter $property $type $field $defaultValue )
+#if ($property.isPartialStateHolder())
+ public void $utils.getPrefixedPropertyName("set", $property.name)($type $utils.getVariableFromName($property.name))
+ {
+ this.$field = $utils.getVariableFromName($property.name);
+ if (initialStateMarked())
+ {
+ getStateHelper().put(PropertyKeys.${property.name}Set,Boolean.TRUE);
+ }
+#if ($utils.isPrimitiveClass($type) && !$property.isTagExcluded() && $property.isSetMethod())
+ this.${field}Set = true;
+#end
+ }
+
+#else
+ public void $utils.getPrefixedPropertyName("set", $property.name)($type $utils.getVariableFromName($property.name))
+ {
+ getStateHelper().put(PropertyKeys.$field, $utils.getVariableFromName($property.name) );
+#if ($utils.isPrimitiveClass($type) && !$property.isTagExcluded() && $property.isSetMethod())
+ this.${field}Set = true;
+#end
+ }
+
+#end
+#end
+##
## ----------------------------- END PROPERTY MACROS -------------------------
##
## ----------------------------- START PROPERTY RENDERING --------------------
@@ -190,12 +351,28 @@ public class ${utils.getClassFromFullCla
#set ($defaultValue = false)
#end
// Property: $property.name
+#if ($validator.isEvaluateELOnExecution())
+#if ($property.name == "for")
+## To keep compatibility with RI, we should call it forVal
+#set ($field = "forVal")
+#else
+#set ($field = $property.name)
+#end
+## USING PARTIAL STATE SAVING STATE HELPER
+#writePropertyStateHelperDeclaration($property $type $field $defaultValue)
+#writeLocalPropertyStateHelperGetter ($property $type $field $defaultValue)
+#writePropertyStateHelperGetter ($property $type $field $defaultValue)
+#writePropertyStateHelperSetter ($property $type $field $defaultValue)
+#else
+## USING VARIABLES
#writePropertyDeclaration($property $type $field $defaultValue)
#writeLocalPropertyGetter ($property $type $field $defaultValue)
#writePropertyGetter ($property $type $field $defaultValue)
#writePropertySetter ($property $type $field $defaultValue)
#end
+#end
## ----------------------------- END PROPERTY RENDERING ---------------------
+#if ( !($validator.isEvaluateELOnExecution()) )
public Object saveState(FacesContext facesContext)
{
@@ -259,4 +436,215 @@ public class ${utils.getClassFromFullCla
#end
#end
}
+#else
+ enum PropertyKeys
+ {
+
+#set ($comma = "")
+#set ($addc = "false")
+#foreach( $property in $propertyList )
+#if ($property.name == "for")
+#set ($addc = "true")
+## To keep compatibility with RI, we should call it forVal
+#set ($field = "forVal")
+#else
+#set ($field = $property.name)
+#end
+#set ($type = $utils.getClassFromFullClass($property.className))
+#if($utils.getDefaultValueField($property))
+#set ($defaultValue = $utils.getDefaultValueField($property))
+#else
+#set ($defaultValue = false)
+#end
+#if ($property.name == "for")
+ $comma $field("for")
+#else
+#if ($property.isPartialStateHolder())
+ $comma ${field}Set
+#else
+ $comma $field
+#end
+#end
+#set($comma = ",")
+#end
+#if ("true" == $addc)
+ ;
+ String c;
+
+ PropertyKeys()
+ {
+ }
+
+ //Constructor needed by "for" property
+ PropertyKeys(String c)
+ {
+ this.c = c;
+ }
+
+ public String toString()
+ {
+ return ((this.c != null) ? this.c : super.toString());
+ }
+#end
+ }
+
+#set ($primitiveCount = 1) ## $propertyList.size() + 1
+#foreach( $property in $propertyList )
+#if ($property.isPartialStateHolder())
+#set ($primitiveCount = $primitiveCount + 1)
+#if($utils.isPrimitiveClass($property.className))
+#set ($primitiveCount = $primitiveCount + 1)
+#end
+#end
+#end
+## saveState and restoreState methods only has sense if we have properties
+## that does not use StateHelper class.
+#if ($primitiveCount > 1)
+
+ public void markInitialState()
+ {
+ super.markInitialState();
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#if ($property.isPartialStateHolder())
+ if ($field != null &&
+ $field instanceof PartialStateHolder)
+ {
+ ((PartialStateHolder)$field).markInitialState();
+ }
+#end
+#end
+ }
+
+ public void clearInitialState()
+ {
+ if (initialStateMarked())
+ {
+ super.clearInitialState();
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#if ($property.isPartialStateHolder())
+## //Only has sense propagate this method if is initialStateMarked
+ if ($field != null &&
+ $field instanceof PartialStateHolder)
+ {
+ ((PartialStateHolder)$field).clearInitialState();
+ }
+#end
+#end
+ }
+ }
+
+ @Override
+ public Object saveState(FacesContext facesContext)
+ {
+ if (initialStateMarked())
+ {
+ boolean nullDelta = true;
+ Object parentSaved = super.saveState(facesContext);
+#set ($arrayIndex = 0)
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $property.className)
+#if ($property.isPartialStateHolder())
+#set ($arrayIndex = $arrayIndex + 1)
+ Object ${property.name}Saved = null;
+ if (!_$utils.getPrefixedPropertyName("isSet", $property.name)() &&
+ $field != null && $field instanceof PartialStateHolder)
+ {
+ //Delta
+ StateHolder holder = (StateHolder) $field;
+ if (!holder.isTransient())
+ {
+ Object attachedState = holder.saveState(facesContext);
+ if (attachedState != null)
+ {
+ nullDelta = false;
+ }
+ ${property.name}Saved = new _AttachedDeltaWrapper(${field}.getClass(),
+ attachedState);
+ }
+ }
+ else if (_$utils.getPrefixedPropertyName("isSet", $property.name)() || $field != null )
+ {
+ //Full
+ ${property.name}Saved = saveAttachedState(facesContext,$field);
+ nullDelta = false;
+ }
+## StateHelper Properties does not need save and restore
+#end
+#end
+ if (parentSaved == null && nullDelta)
+ {
+ //No values
+ return null;
+ }
+
+ Object[] values = new Object[$primitiveCount];
+ values[0] = parentSaved;
+## Save full state
+#set ($arrayIndex = 0)
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $property.className)
+#if ($property.isPartialStateHolder())
+#set ($arrayIndex = $arrayIndex + 1)
+ values[$arrayIndex] = ${property.name}Saved;
+## StateHelper Properties does not need save and restore
+#end
+#end
+ return values;
+ }
+ else
+ {
+ Object[] values = new Object[$primitiveCount];
+ values[0] = super.saveState(facesContext);
+## Save full state
+#set ($arrayIndex = 0)
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $property.className)
+#if ($property.isPartialStateHolder())
+#set ($arrayIndex = $arrayIndex + 1)
+ values[$arrayIndex] = saveAttachedState(facesContext,$field);
+## StateHelper Properties does not need save and restore
+#end
+#end
+ return values;
+ }
+ }
+
+ @Override
+ public void restoreState(FacesContext facesContext, Object state)
+ {
+ if (state == null)
+ {
+ return;
+ }
+
+ Object[] values = (Object[])state;
+ super.restoreState(facesContext,values[0]);
+#set ($arrayIndex = 0)
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $property.className)
+#if ($property.isPartialStateHolder())
+#set ($arrayIndex = $arrayIndex + 1)
+ if (values[$arrayIndex] instanceof _AttachedDeltaWrapper)
+ {
+ //Delta
+ ((StateHolder)$field).restoreState(facesContext, ((_AttachedDeltaWrapper) values[$arrayIndex]).getWrappedStateObject());
+ }
+ else
+ {
+ //Full
+ $field = $utils.castIfNecessary($type) restoreAttachedState(facesContext,values[$arrayIndex]);
+ }
+#else
+## StateHelper Properties does not need save and restore
+#end
+#end
+ }
+#end
+#end
}