You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by bs...@apache.org on 2011/02/02 07:05:24 UTC

svn commit: r1066337 - /myfaces/trinidad/branches/1.2.12.3.4-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/RowKeySetAttributeChange.java

Author: bsullivan
Date: Wed Feb  2 06:05:24 2011
New Revision: 1066337

URL: http://svn.apache.org/viewvc?rev=1066337&view=rev
Log:
TRINIDAD-2011 RowKeySet Attribute Changes surprisingly change object identity

Modified:
    myfaces/trinidad/branches/1.2.12.3.4-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/RowKeySetAttributeChange.java

Modified: myfaces/trinidad/branches/1.2.12.3.4-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/RowKeySetAttributeChange.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.12.3.4-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/RowKeySetAttributeChange.java?rev=1066337&r1=1066336&r2=1066337&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.12.3.4-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/RowKeySetAttributeChange.java (original)
+++ myfaces/trinidad/branches/1.2.12.3.4-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/RowKeySetAttributeChange.java Wed Feb  2 06:05:24 2011
@@ -11,7 +11,11 @@ import javax.faces.el.ValueBinding;
 
 import org.apache.myfaces.trinidad.model.RowKeySet;
 
-public class RowKeySetAttributeChange extends AttributeComponentChange
+/**
+ * Handles RowKeySetAttribute changes, which need to be handled specially because they are mutable
+ * and programmers assume that the instances don't change
+ */
+public final class RowKeySetAttributeChange extends AttributeComponentChange
 {
   public RowKeySetAttributeChange(String clientId,  String propertyName, Object value)
   {
@@ -47,9 +51,7 @@ public class RowKeySetAttributeChange ex
       attributeMap.remove(attributeName);
     }
     else
-    {
-      boolean putValue = true;
-      
+    {      
       // Specially handle RowKeySet case by replacing the contents of the RowKeySet in-place
       // rather than replacing the entire object.  This keeps the mutable object instance from
       // changing
@@ -61,60 +63,99 @@ public class RowKeySetAttributeChange ex
         
         if (expression != null)
         {
+          //use EL to get the oldValue and then determine whether we need to update in place
           final FacesContext context = FacesContext.getCurrentInstance();
-          
-          RowKeySet[] outHolder = new RowKeySet[1];
-          
-          context.getViewRoot().invokeOnComponent(context,
-                                                 _clientId,
-                                                 new ExpressionEvaluator(expression, outHolder));
-          
-          oldValue = outHolder[0];
+                    
+          context.getViewRoot().invokeOnComponent(
+            context,
+            _clientId,
+            new GetOldValueAndUpdate(expression, (RowKeySet)attributeValue));
         }
         else
         {
           oldValue = attributeMap.get(attributeName);
-        }
-                
-        if (oldValue instanceof RowKeySet)
-        {
-          RowKeySet oldKeySet = (RowKeySet)oldValue;
-          
-          // check for equality because otherwise we would clear ourselves and end up empty
-          if (oldKeySet != attributeValue)
+
+          if (oldValue instanceof RowKeySet)
           {
-            oldKeySet.clear();
-            oldKeySet.addAll((RowKeySet)attributeValue);
+            _updateKeySet(_clientId, (RowKeySet)oldValue, (RowKeySet)attributeValue);
+            
+            // we updated in place, but we still need to set the attribute in order for partial
+            // state saving to work
           }
-          
-          // don't replace the RowKeySet
-          putValue = false;
-        }
+        }      
       }
       
       
-      if (putValue)
+      attributeMap.put(attributeName, attributeValue);
+    }
+  }
+  
+  private static void _updateKeySet(String clientId, RowKeySet oldKeySet, RowKeySet newKeySet)
+  {
+    // check for equality because otherwise we would clear ourselves and end up empty
+    if (oldKeySet != newKeySet)
+    {
+      // no client id, so we're in context
+      if (clientId == null)
       {
-        attributeMap.put(attributeName, attributeValue);
+        oldKeySet.clear();
+        oldKeySet.addAll(newKeySet);        
       }
-    }
+      else
+      {
+        final FacesContext context = FacesContext.getCurrentInstance();
+        
+        context.getViewRoot().invokeOnComponent(
+           context,
+           clientId,
+           new RowKeySetUpdater(oldKeySet, newKeySet));
+      }
+    }    
   }
   
-  private static final class ExpressionEvaluator implements ContextCallback
+  /**
+   * Get the oldValue in context and update it in context
+   */
+  private static final class GetOldValueAndUpdate implements ContextCallback
   {
-    public ExpressionEvaluator(ValueExpression expression, RowKeySet[] out)
+    public GetOldValueAndUpdate(ValueExpression expression, RowKeySet newKeySet)
     {
-      _out        = out;
       _expression = expression;
+      _newKeySet  = newKeySet;
     }
     public void invokeContextCallback(FacesContext context,
                                       UIComponent target)
     {
-      _out[0] = (RowKeySet)_expression.getValue(context.getELContext());
+      // update the KeySet with the old and new values
+      RowKeySetAttributeChange._updateKeySet(null,
+                                             (RowKeySet)_expression.getValue(context.getELContext()),
+                                             _newKeySet);
     }
     
-    private final RowKeySet[] _out;
     private final ValueExpression _expression;
+    private final RowKeySet _newKeySet;
+  }
+
+  /**
+   * Makes sure that we clear and add the RowKeySet in context
+   */
+  private static final class RowKeySetUpdater implements ContextCallback
+  {
+    public RowKeySetUpdater(RowKeySet oldKeySet, RowKeySet newKeySet)
+    {
+      _oldKeySet = oldKeySet;
+      _newKeySet = newKeySet;
+    }
+
+    public void invokeContextCallback(FacesContext context,
+                                      UIComponent target)
+    {
+      _oldKeySet.clear();
+      _oldKeySet.addAll(_newKeySet);
+    }
+    
+    private final RowKeySet _oldKeySet;
+    private final RowKeySet _newKeySet;
   }
 
   private static final long serialVersionUID = 1L;