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 2011/02/06 01:39:39 UTC

svn commit: r1067555 [1/2] - in /myfaces/tomahawk/trunk/sandbox/core20: ./ src/main/conf/META-INF/ src/main/java/org/apache/myfaces/custom/behavior/ src/main/java/org/apache/myfaces/custom/inputAjax/ src/main/java/org/apache/myfaces/custom/suggestajax/...

Author: lu4242
Date: Sun Feb  6 00:39:39 2011
New Revision: 1067555

URL: http://svn.apache.org/viewvc?rev=1067555&view=rev
Log:
TOMAHAWK-1558 Create custom base class for ClientBehaviors

Added:
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBase.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBaseTagHandler.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedListStateWrapper.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedStateWrapper.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_ClientBehaviorRule.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_DeltaStateHelper.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/clientBehaviorClass20.vm
Removed:
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/inputAjax/
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/suggestajax/
Modified:
    myfaces/tomahawk/trunk/sandbox/core20/pom.xml
    myfaces/tomahawk/trunk/sandbox/core20/src/main/conf/META-INF/faces-config-base.xml
    myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/facelets-taglib20.vm
    myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/faces-config20.vm

Modified: myfaces/tomahawk/trunk/sandbox/core20/pom.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/pom.xml?rev=1067555&r1=1067554&r2=1067555&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/pom.xml (original)
+++ myfaces/tomahawk/trunk/sandbox/core20/pom.xml Sun Feb  6 00:39:39 2011
@@ -269,7 +269,36 @@
                         org/apache/myfaces/custom/submitOnEvent/**/*.java,
                         org/apache/myfaces/custom/suggestajax/**/*.java,
                         org/apache/myfaces/custom/table/**/*.java,
-                        org/apache/myfaces/custom/timednotifier/**/*.java
+                        org/apache/myfaces/custom/timednotifier/**/*.java,
+                        org/apache/myfaces/convert/ex/**/*.java,
+                        org/apache/myfaces/custom/ajax/**/*.java,
+                        org/apache/myfaces/custom/autoupdatedatatable/**/*.java,
+                        org/apache/myfaces/custom/clientvalidation/**/*.java,
+                        org/apache/myfaces/custom/comparetovalidator/**/*.java,
+                        org/apache/myfaces/custom/conversation/**/*.java,
+                        org/apache/myfaces/custom/convertboolean/**/*.java,
+                        org/apache/myfaces/custom/convertDateTime/**/*.java,
+                        org/apache/myfaces/custom/convertNumber/**/*.java,
+                        org/apache/myfaces/custom/csvvalidator/**/*.java,
+                        org/apache/myfaces/custom/dynamicResources/**/*.java,
+                        org/apache/myfaces/custom/exporter/**/*.java,
+                        org/apache/myfaces/custom/form/**/*.java,
+                        org/apache/myfaces/custom/globalId/**/*.java,
+                        org/apache/myfaces/custom/graphicimagedynamic/**/*.java,
+                        org/apache/myfaces/custom/inputAjax/**/*.java,
+                        org/apache/myfaces/custom/isbnvalidator/**/*.java,
+                        org/apache/myfaces/custom/outputlinkdynamic/**/*.java,
+                        org/apache/myfaces/custom/redirectTracker/**/*.java,
+                        org/apache/myfaces/custom/renderOne/**/*.java,
+                        org/apache/myfaces/custom/requestParameterProvider/**/*.java,
+                        org/apache/myfaces/custom/scope/**/*.java,
+                        org/apache/myfaces/custom/security/**/*.java,
+                        org/apache/myfaces/custom/suggest/**/*.java,
+                        org/apache/myfaces/custom/urlvalidator/**/*.java,
+                        org/apache/myfaces/custom/util/**/*.java,
+                        org/apache/myfaces/renderkit/**/*.java,
+                        org/apache/myfaces/tomahawk/util/**/*.java,
+                        org/apache/myfaces/validator/ex/**/*.java
                         </excludes>
                       </artifactItem>
                     </artifactItems>
@@ -354,6 +383,15 @@
                     </configuration>
                 </execution>
                 <execution>
+                    <id>make-client-behaviors</id>
+                    <goals>
+                      <goal>make-client-behaviors</goal>
+                    </goals>
+                    <configuration>
+                       <mainSourceDirectory2>${project.build.directory}/tomahawk12_sources</mainSourceDirectory2>
+                    </configuration>
+                </execution>
+                <execution>
                     <id>maketags</id>
                     <configuration>
                        <jsfVersion>12</jsfVersion>
@@ -379,7 +417,7 @@
                   <configuration>
                       <xmlFile>META-INF/myfaces_sandbox.tld</xmlFile>
                       <xmlBaseFile>src/main/conf/META-INF/myfaces_sandbox-base.tld</xmlBaseFile>
-                      <templateFile>tomahawk12.vm</templateFile>
+                      <templateFile>tld-tomahawk20.vm</templateFile>
                       <params>
                          <shortname>s</shortname>
                          <uri>http://myfaces.apache.org/sandbox</uri>
@@ -387,7 +425,7 @@
                          <description>Enhanced standard JSP actions and custom MyFaces actions.</description>
                       </params>
                       <modelIds>
-                          <modelId>tomahawk-sandbox12</modelId>
+                          <modelId>tomahawk-sandbox20</modelId>
                       </modelIds>
                   </configuration>
                   <goals>
@@ -405,7 +443,7 @@
                          <uri>http://myfaces.apache.org/sandbox</uri>
                       </params>
                       <modelIds>
-                          <modelId>tomahawk-sandbox12</modelId>
+                          <modelId>tomahawk-sandbox20</modelId>
                       </modelIds>
                   </configuration>
                   <goals>

Modified: myfaces/tomahawk/trunk/sandbox/core20/src/main/conf/META-INF/faces-config-base.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/conf/META-INF/faces-config-base.xml?rev=1067555&r1=1067554&r2=1067555&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/conf/META-INF/faces-config-base.xml (original)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/conf/META-INF/faces-config-base.xml Sun Feb  6 00:39:39 2011
@@ -21,16 +21,31 @@
 
 <faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" 
-              version="1.2">
-              
+              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" 
+              version="2.0">
+
+
   <lifecycle>
+      <!--               
       <phase-listener>org.apache.myfaces.custom.ajax.api.AjaxDecodePhaseListener</phase-listener>
+      -->
       <phase-listener>org.apache.myfaces.custom.valueChangeNotifier.ValueChangePhaseListener</phase-listener>
+      <!--
       <phase-listener>org.apache.myfaces.custom.redirectTracker.RedirectTrackerPhaseListener</phase-listener>
-      <phase-listener>org.apache.myfaces.custom.ppr.PPRPhaseListener</phase-listener> 
+      <phase-listener>org.apache.myfaces.custom.ppr.PPRPhaseListener</phase-listener>
+      --> 
   </lifecycle>
-
+  
+  <!-- 
+  <render-kit>
+     <client-behavior-renderer>
+        <client-behavior-renderer-type>org.apache.myfaces.custom.effect.EffectAppearBehavior</client-behavior-renderer-type>
+        <client-behavior-renderer-class>org.apache.myfaces.custom.effect.EffectAppearClientBehaviorRenderer</client-behavior-renderer-class>
+     </client-behavior-renderer>
+  </render-kit>
+   -->
+  
+  <!--
   <application>
     <variable-resolver>org.apache.myfaces.custom.redirectTracker.RedirectTrackerVariableResolver</variable-resolver>
     <navigation-handler>org.apache.myfaces.custom.redirectTracker.RedirectTrackerNavigationHandler</navigation-handler>
@@ -41,8 +56,10 @@
   <factory>
       <lifecycle-factory>org.apache.myfaces.custom.ppr.PPRLifecycleFactory</lifecycle-factory>
   </factory>
+   -->
 
   <!-- sandbox managed beans -->
+  <!-- 
   <managed-bean>
     <managed-bean-name>ScopeContainer</managed-bean-name>
     <managed-bean-class>org.apache.myfaces.custom.scope.ScopeHolder</managed-bean-class>
@@ -55,8 +72,10 @@
         </managed-bean-class>
         <managed-bean-scope>request</managed-bean-scope>
   </managed-bean>
-
+ -->
+ 
   <!-- extended converters and validators -->
+  <!-- 
     <converter>
         <converter-id>javax.faces.Integer</converter-id>
         <converter-class>org.apache.myfaces.convert.ex.IntegerConverter</converter-class>
@@ -110,5 +129,6 @@
         <validator-id>javax.faces.DoubleRange</validator-id>
         <validator-class>org.apache.myfaces.validator.ex.DoubleRangeValidator</validator-class>
     </validator>
+     -->
 
 </faces-config>

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBase.java?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBase.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBase.java Sun Feb  6 00:39:39 2011
@@ -0,0 +1,325 @@
+/*
+ * 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.custom.behavior;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+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.context.FacesContext;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFClientBehavior;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+
+/**
+ * Base behavior implementation for Apache MyFaces Tomahawk.
+ *
+ */
+@JSFClientBehavior(
+        configExcluded = true,
+        evaluateELOnExecution = true,
+        tagHandler = "org.apache.myfaces.custom.behavior.ClientBehaviorBaseTagHandler")
+public abstract class ClientBehaviorBase extends
+        javax.faces.component.behavior.ClientBehaviorBase
+{
+
+    private transient FacesContext _facesContext;
+    private StateHelper _stateHelper = null;
+
+    /**
+     * @param context
+     */
+    @Override
+    public Object saveState(FacesContext facesContext)
+    {
+        if (initialStateMarked())
+        {
+            Object parentSaved = super.saveState(facesContext);
+            Object stateHelperSaved = null;
+            StateHelper stateHelper = getStateHelper(false);
+            if (stateHelper != null)
+            {
+                stateHelperSaved = stateHelper.saveState(facesContext);
+            }
+
+            if (parentSaved == null && stateHelperSaved == null)
+            {
+                //No values
+                return null;
+            }
+            return new Object[] { parentSaved, stateHelperSaved };
+        }
+        else
+        {
+            Object[] values = new Object[2];
+            values[0] = super.saveState(facesContext);
+            StateHelper stateHelper = getStateHelper(false);
+            if (stateHelper != null)
+            {
+                values[1] = stateHelper.saveState(facesContext);
+            }
+            return values;
+        }
+    }
+
+    @Override
+    public void restoreState(FacesContext facesContext, Object o)
+    {
+        if (o == null)
+        {
+            return;
+        }
+        Object[] values = (Object[]) o;
+        if (values[0] != null)
+        {
+            super.restoreState(facesContext, values[0]);
+        }
+        getStateHelper().restoreState(facesContext, values[1]);
+    }
+
+    // --------------------- borrowed from UIComponentBase ------------
+
+    @SuppressWarnings("unchecked")
+    public ValueExpression getValueExpression(String name)
+    {
+        if (name == null)
+            throw new NullPointerException("name");
+        StateHelper helper = getStateHelper(false);
+        if (helper == null)
+        {
+            return null;
+        }
+        Map<String, Object> bindings = (Map<String, Object>) helper
+                .get(PropertyKeys.bindings);
+        if (bindings == null)
+        {
+            return null;
+        }
+        else
+        {
+            return (ValueExpression) bindings.get(name);
+        }
+    }
+
+    public void setValueExpression(String name, ValueExpression expression)
+    {
+        if (name == null)
+            throw new NullPointerException("name");
+        if (expression == null)
+        {
+            getStateHelper().remove(PropertyKeys.bindings, name);
+        }
+        else
+        {
+            getStateHelper().put(PropertyKeys.bindings, name, expression);
+        }
+    }
+
+    /**
+     * Serializes objects which are "attached" to this component but which are
+     * not UIComponent children of it. Examples are validator and listener
+     * objects. To be precise, it returns an object which implements
+     * java.io.Serializable, and which when serialized will persist the
+     * state of the provided object.
+     * <p>
+     * If the attachedObject is a List then every object in the list is saved
+     * via a call to this method, and the returned wrapper object contains
+     * a List object.
+     * <p>
+     * If the object implements StateHolder then the object's saveState is
+     * called immediately, and a wrapper is returned which contains both
+     * this saved state and the original class name. However in the case
+     * where the StateHolder.isTransient method returns true, null is
+     * returned instead.
+     * <p>
+     * If the object implements java.io.Serializable then the object is simply
+     * returned immediately; standard java serialization will later be used
+     * to store this object.
+     * <p>
+     * In all other cases, a wrapper is returned which simply stores the type
+     * of the provided object. When deserialized, a default instance of that
+     * type will be recreated.
+     */
+    public static Object saveAttachedState(FacesContext context,
+            Object attachedObject)
+    {
+        if (context == null)
+        {
+            throw new NullPointerException("context");
+        }
+
+        if (attachedObject == null)
+            return null;
+        // StateHolder interface should take precedence over
+        // List children
+        if (attachedObject instanceof StateHolder)
+        {
+            StateHolder holder = (StateHolder) attachedObject;
+            if (holder.isTransient())
+            {
+                return null;
+            }
+
+            return new _AttachedStateWrapper(attachedObject.getClass(),
+                    holder.saveState(context));
+        }
+        else if (attachedObject instanceof List)
+        {
+            List<Object> lst = new ArrayList<Object>(
+                    ((List<?>) attachedObject).size());
+            for (Object item : (List<?>) attachedObject)
+            {
+                if (item != null)
+                {
+                    lst.add(saveAttachedState(context, item));
+                }
+            }
+
+            return new _AttachedListStateWrapper(lst);
+        }
+        else if (attachedObject instanceof Serializable)
+        {
+            return attachedObject;
+        }
+        else
+        {
+            return new _AttachedStateWrapper(attachedObject.getClass(), null);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Object restoreAttachedState(FacesContext context,
+            Object stateObj) throws IllegalStateException
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        if (stateObj == null)
+            return null;
+        if (stateObj instanceof _AttachedListStateWrapper)
+        {
+            List<Object> lst = ((_AttachedListStateWrapper) stateObj)
+                    .getWrappedStateList();
+            List<Object> restoredList = new ArrayList<Object>(lst.size());
+            for (Object item : lst)
+            {
+                restoredList.add(restoreAttachedState(context, item));
+            }
+            return restoredList;
+        }
+        else if (stateObj instanceof _AttachedStateWrapper)
+        {
+            Class<?> clazz = ((_AttachedStateWrapper) stateObj).getClazz();
+            Object restoredObject;
+            try
+            {
+                restoredObject = clazz.newInstance();
+            }
+            catch (InstantiationException e)
+            {
+                throw new RuntimeException(
+                        "Could not restore StateHolder of type "
+                                + clazz.getName()
+                                + " (missing no-args constructor?)", e);
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new RuntimeException(e);
+            }
+            if (restoredObject instanceof StateHolder)
+            {
+                _AttachedStateWrapper wrapper = (_AttachedStateWrapper) stateObj;
+                Object wrappedState = wrapper.getWrappedStateObject();
+
+                StateHolder holder = (StateHolder) restoredObject;
+                holder.restoreState(context, wrappedState);
+            }
+            return restoredObject;
+        }
+        else
+        {
+            return stateObj;
+        }
+    }
+
+    protected FacesContext getFacesContext()
+    {
+        if (_facesContext == null)
+        {
+            return FacesContext.getCurrentInstance();
+        }
+        else
+        {
+            return _facesContext;
+        }
+    }
+
+    boolean isCachedFacesContext()
+    {
+        return _facesContext != null;
+    }
+
+    void setCachedFacesContext(FacesContext facesContext)
+    {
+        _facesContext = facesContext;
+    }
+
+    protected StateHelper getStateHelper()
+    {
+        return getStateHelper(true);
+    }
+
+    /**
+     * returns a delta state saving enabled state helper
+     * for the current component
+     * @param create if true a state helper is created if not already existing
+     * @return an implementation of the StateHelper interface or null if none exists and create is set to false
+     */
+    protected StateHelper getStateHelper(boolean create)
+    {
+        if (_stateHelper != null)
+        {
+            return _stateHelper;
+        }
+        if (create)
+        {
+            _stateHelper = new _DeltaStateHelper(this);
+        }
+        return _stateHelper;
+    }
+    
+    /**
+     * The event that this client behavior should be attached.
+     * 
+     * @return
+     */
+    @JSFProperty
+    private String getEvent()
+    {
+        return null;
+    }
+
+    enum PropertyKeys
+    {
+        bindings
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBaseTagHandler.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBaseTagHandler.java?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBaseTagHandler.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/ClientBehaviorBaseTagHandler.java Sun Feb  6 00:39:39 2011
@@ -0,0 +1,47 @@
+/*
+ * 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.custom.behavior;
+
+import javax.faces.view.facelets.BehaviorConfig;
+import javax.faces.view.facelets.BehaviorHandler;
+import javax.faces.view.facelets.MetaRuleset;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
+
+@JSFFaceletTag
+public class ClientBehaviorBaseTagHandler extends BehaviorHandler
+{
+
+    public ClientBehaviorBaseTagHandler(BehaviorConfig config)
+    {
+        super(config);
+    }
+
+    @Override
+    protected MetaRuleset createMetaRuleset(Class type)
+    {
+        MetaRuleset ruleSet = super.createMetaRuleset(type);
+        
+        //Add rule to handle EL expressions
+        ruleSet.addRule(_ClientBehaviorRule.Instance);
+        
+        return ruleSet;
+    }
+
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedListStateWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedListStateWrapper.java?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedListStateWrapper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedListStateWrapper.java Sun Feb  6 00:39:39 2011
@@ -0,0 +1,43 @@
+/*
+ * 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.custom.behavior;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author Manfred Geiler (latest modification by $Author: bdudney $)
+ * @version $Revision: 225333 $ $Date: 2005-07-26 17:49:19 +0200 (Di, 26 Jul 2005) $
+ */
+class _AttachedListStateWrapper
+        implements Serializable
+{
+    private static final long serialVersionUID = -3958718149793179776L;
+    private List _wrappedStateList;
+
+    public _AttachedListStateWrapper(List wrappedStateList)
+    {
+        _wrappedStateList = wrappedStateList;
+    }
+
+    public List getWrappedStateList()
+    {
+        return _wrappedStateList;
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedStateWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedStateWrapper.java?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedStateWrapper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_AttachedStateWrapper.java Sun Feb  6 00:39:39 2011
@@ -0,0 +1,57 @@
+/*
+ * 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.custom.behavior;
+
+import java.io.Serializable;
+
+/**
+ * @author Manfred Geiler (latest modification by $Author: bdudney $)
+ * @version $Revision: 225333 $ $Date: 2005-07-26 17:49:19 +0200 (Di, 26 Jul 2005) $
+ */
+class _AttachedStateWrapper
+        implements Serializable
+{
+    private static final long serialVersionUID = 4948301780259917764L;
+    private Class _class;
+    private Object _wrappedStateObject;
+
+    /**
+     * @param clazz null means wrappedStateObject is a List of state objects
+     * @param wrappedStateObject
+     */
+    public _AttachedStateWrapper(Class clazz, Object wrappedStateObject)
+    {
+        if (wrappedStateObject != null && !(wrappedStateObject instanceof Serializable))
+        {
+            throw new IllegalArgumentException("Attached state for Object of type " + clazz + " (Class " + wrappedStateObject.getClass().getName() + ") is not serializable");
+        }
+        _class = clazz;
+        _wrappedStateObject = wrappedStateObject;
+    }
+
+    public Class getClazz()
+    {
+        return _class;
+    }
+
+    public Object getWrappedStateObject()
+    {
+        return _wrappedStateObject;
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_ClientBehaviorRule.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_ClientBehaviorRule.java?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_ClientBehaviorRule.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_ClientBehaviorRule.java Sun Feb  6 00:39:39 2011
@@ -0,0 +1,99 @@
+/*
+ * 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.custom.behavior;
+
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+final class _ClientBehaviorRule extends MetaRule {
+
+    final static class ValueExpressionMetadata extends Metadata {
+
+        private final String name;
+
+        private final TagAttribute attr;
+
+        private final Class type;
+
+        public ValueExpressionMetadata(String name, Class type,
+                TagAttribute attr) {
+            this.name = name;
+            this.attr = attr;
+            this.type = type;
+        }
+
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            ((ClientBehaviorBase) instance).setValueExpression(this.name, this.attr
+                    .getValueExpression(ctx, this.type));
+        }
+
+    }
+
+    /*
+    final static class ValueBindingMetadata extends Metadata {
+
+        private final String name;
+
+        private final TagAttribute attr;
+
+        private final Class type;
+
+        public ValueBindingMetadata(String name, Class type, TagAttribute attr) {
+            this.name = name;
+            this.attr = attr;
+            this.type = type;
+        }
+
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            ((ValidatorBase) instance).setValueBinding(this.name,
+                    new LegacyValueBinding(this.attr.getValueExpression(ctx,
+                            this.type)));
+        }
+
+    }*/
+
+    public final static _ClientBehaviorRule Instance = new _ClientBehaviorRule();
+
+    public _ClientBehaviorRule() {
+        super();
+    }
+
+    public Metadata applyRule(String name, TagAttribute attribute,
+            MetadataTarget meta) {
+        if (meta.isTargetInstanceOf(ClientBehaviorBase.class)) {
+
+            // if component and dynamic, then must set expression
+            if (!attribute.isLiteral()) {
+                Class type = meta.getPropertyType(name);
+                if (type == null) {
+                    type = Object.class;
+                }
+                //if (FacesAPI.getComponentVersion(meta.getTargetClass()) >= 12) {
+                    return new ValueExpressionMetadata(name, type, attribute);
+                //} else {
+                //    return new ValueBindingMetadata(name, type, attribute);
+                //}
+            }
+        }
+        return null;
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_DeltaStateHelper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_DeltaStateHelper.java?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_DeltaStateHelper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/behavior/_DeltaStateHelper.java Sun Feb  6 00:39:39 2011
@@ -0,0 +1,825 @@
+/*
+ * 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.custom.behavior;
+
+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.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 ClientBehaviorBase _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(ClientBehaviorBase 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 = ClientBehaviorBase.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] = ValidatorBase.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 = ClientBehaviorBase.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) ClientBehaviorBase
+                        .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] = ClientBehaviorBase.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) ClientBehaviorBase.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] = ClientBehaviorBase.saveAttachedState(context, value);
+                }
+                else
+                {
+                    values[i] = value;
+                }                
+            }
+            return values;
+        }
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/clientBehaviorClass20.vm
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/clientBehaviorClass20.vm?rev=1067555&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/clientBehaviorClass20.vm (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/resources/META-INF/clientBehaviorClass20.vm Sun Feb  6 00:39:39 2011
@@ -0,0 +1,668 @@
+## Velocity template used to generate JSF1.2-compatible clientBehavior classes
+## from clientBehavior meta-data.
+##
+## Note that there are only one type of clientBehavior generation:
+##  * "subclass mode" (use annotated class as a parent class)
+##
+## Variable $clientBehavior refers to a BehaviorMeta object to process
+## Variable $utils refers to an instance of MyfacesUtils.
+##
+##
+## The java package of the generated class is always the same as
+## the package in which the annotated class exists.
+##
+/*
+ *  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 ${clientBehavior.packageName};
+
+import javax.el.ValueExpression;
+import javax.faces.context.FacesContext;
+$utils.importTagClasses($clientBehavior)
+
+#if ($clientBehavior.isTemplate())
+#set ($generatedClassParent = $clientBehavior.sourceClassParentClassName)
+#else
+#set ($generatedClassParent = $clientBehavior.sourceClassName)
+#end
+// Generated from class ${clientBehavior.sourceClassName}.
+//
+// WARNING: This file was automatically generated. Do not edit it directly,
+//          or you will lose your changes.
+public class ${utils.getClassFromFullClass($clientBehavior.className)} extends $generatedClassParent
+#if ($clientBehavior.implements)
+    implements $clientBehavior.implements
+#end
+{
+
+#if ($clientBehavior.behaviorId)
+    static public final String BEHAVIOR_ID = 
+        "$clientBehavior.behaviorId";
+#end
+#if ($clientBehavior.rendererType)
+#if (!($clientBehavior.rendererType == ""))
+    static public final String RENDERER_TYPE = 
+        "$clientBehavior.rendererType";
+#end
+#end
+
+    public ${utils.getClassFromFullClass($clientBehavior.className)}()
+    {
+    }
+    
+#if ($clientBehavior.rendererType)
+#if ($clientBehavior.rendererType == "")
+#else
+    public String getRendererType()
+    {
+        return "$clientBehavior.rendererType";
+    }
+#end
+#end
+    
+    
+
+## ----------------------------- PROPERTY MACROS -----------------------------
+##
+## -------------------------------
+## writePropertySetDeclaration
+## -------------------------------
+##
+#macro (writePropertySetDeclaration $property $type $field $defaultValue )
+#if($utils.isPrimitiveClass($type) && !$property.isTagExcluded() )
+    private boolean ${field}Set;
+    
+#end
+#end
+##
+## -------------------------------
+## writePropertyDeclaration
+## -------------------------------
+##
+#macro( writePropertyDeclaration $property $type $field $defaultValue )
+#if ($property.isLiteralOnly() || $property.isTagExcluded() || !($clientBehavior.isEvaluateELOnExecution()))
+    private $type $field #if($defaultValue) = $defaultValue;#{else};#{end}
+
+#else
+    private $type $field;
+    
+#end
+#writePropertySetDeclaration ($property $type $field $defaultValue)
+#end
+##
+## -------------------------------
+## writeLocalPropertyGetter
+## -------------------------------
+##
+#macro (writeLocalPropertyGetter $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}()
+    {
+        return $field;
+    }
+
+#end
+#end
+##
+## -------------------------------
+## writePropertyGetter
+## -------------------------------
+##
+#macro (writePropertyGetter $property $type $field $defaultValue )
+    public $type $utils.getMethodReaderFromProperty($property.name, $type)()
+    {
+#if ($property.isTagExcluded() || $property.isLiteralOnly() || !($clientBehavior.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
+    }
+
+#end
+##
+## -------------------------------
+## writePropertySetter
+## -------------------------------
+##
+#macro (writePropertySetter $property $type $field $defaultValue )
+    public void $utils.getPrefixedPropertyName("set", $property.name)($type $utils.getVariableFromName($property.name))
+    {
+        this.$field = $utils.getVariableFromName($property.name);
+#if ($utils.isPrimitiveClass($type) && !$property.isTagExcluded() )
+        this.${field}Set = true;        
+#end
+    }
+
+#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() || !($clientBehavior.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 --------------------
+#set ($propertyList = ${clientBehavior.propertyBehaviorList})
+
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $utils.getClassFromFullClass($property.className))
+#if($utils.getDefaultValueField($property)) 
+#set ($defaultValue = $utils.getDefaultValueField($property))
+#else
+#set ($defaultValue = false)
+#end
+    // Property: $property.name
+#if ($clientBehavior.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 ( !($clientBehavior.isEvaluateELOnExecution()) )
+
+    public Object saveState(FacesContext facesContext)
+    {
+#set ($primitiveCount = $propertyList.size() + 1)
+#foreach( $property in $propertyList )
+#if($utils.isPrimitiveClass($property.className))
+#set ($primitiveCount = $primitiveCount + 1)
+#end
+#end
+        Object[] values = new Object[$primitiveCount];
+        values[0] = super.saveState(facesContext);
+#set ($arrayIndex = 0)
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $property.className)
+#set ($arrayIndex = $arrayIndex + 1)
+#if ($property.jspName == "validator" && $property.isMethodBinding() )
+        values[$arrayIndex] = saveAttachedState(facesContext,${field}List);
+#elseif ( $property.isStateHolder() )## || $utils.isConverter($type)
+        values[$arrayIndex] = saveAttachedState(facesContext,$field);
+#elseif($utils.isPrimitiveClass($type))
+        values[$arrayIndex] = ${utils.getBoxedClass($type)}.valueOf($field);
+#else
+        values[$arrayIndex] = $field;
+#end
+#if($utils.isPrimitiveClass($type) && !$property.isTagExcluded())
+#set ($arrayIndex = $arrayIndex + 1)
+        values[$arrayIndex] = Boolean.valueOf(${field}Set);
+#end
+#end
+        return values; 
+    }
+
+    public void restoreState(FacesContext facesContext, Object state)
+    {
+        Object[] values = (Object[])state;
+        super.restoreState(facesContext,values[0]);
+#set ($arrayIndex = 0)
+#foreach( $property in $propertyList )
+#set ($field = $property.fieldName)
+#set ($type = $property.className)
+#set ($arrayIndex = $arrayIndex + 1)
+#if ( $property.isStateHolder() )
+#if ($property.jspName == "validator" && $property.isMethodBinding() )
+        ${field}List = (List<Validator>) restoreAttachedState(facesContext,values[$arrayIndex]);
+#elseif ($utils.isList($type))
+        $field = (List) restoreAttachedState(facesContext,values[$arrayIndex]);
+#else
+        $field = $utils.castIfNecessary($type) restoreAttachedState(facesContext,values[$arrayIndex]); 
+#end
+#elseif ($utils.isConverter($type)) 
+        $field = (Converter) restoreAttachedState(facesContext,values[$arrayIndex]);
+#elseif ($utils.isPrimitiveClass($type))
+        $field = ($utils.castIfNecessary($type) values[$arrayIndex]).${type}Value();
+#else
+        $field = $utils.castIfNecessary($type) values[$arrayIndex];
+#end
+#if($utils.isPrimitiveClass($type) && !$property.isTagExcluded() )
+#set ($arrayIndex = $arrayIndex + 1)
+        ${field}Set = ((Boolean) values[$arrayIndex]).booleanValue();
+#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
+}