Ensure that EntityProxy instances returned from Collections returned from an editable EntityProxy are editable.
Patch by: bobv
Review by: rjrjr
Found by: pjulien

Review at http://gwt-code-reviews.appspot.com/976801


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9024 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java b/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java
index 6b3c3fa..561de38 100644
--- a/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java
+++ b/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java
@@ -49,8 +49,7 @@
     return stableId(bean).hashCode();
   }
 
-  public static AbstractRequestContext requestContext(
-      AutoBean<? extends EntityProxy> bean) {
+  public static AbstractRequestContext requestContext(AutoBean<?> bean) {
     return (AbstractRequestContext) bean.getTag(REQUEST_CONTEXT);
   }
 
@@ -70,13 +69,11 @@
    * EntityProxy, that its return values are mutable.
    */
   // CHECKSTYLE_OFF
-  public static <T> T __intercept(AutoBean<? extends EntityProxy> bean,
-      T returnValue) {
+  public static <T> T __intercept(AutoBean<?> bean, T returnValue) {
     // CHECKSTYLE_ON
-    if (!(returnValue instanceof EntityProxy)) {
-      return returnValue;
-    }
+
     AbstractRequestContext context = requestContext(bean);
+
     /*
      * The context will be null if the bean is immutable. If the context is
      * locked, don't try to edit.
@@ -85,8 +82,26 @@
       return returnValue;
     }
 
-    @SuppressWarnings("unchecked")
-    T toReturn = (T) context.edit((EntityProxy) returnValue);
-    return toReturn;
+    /*
+     * EntityProxies need to be recorded specially by the RequestContext, so
+     * delegate to the edit() method for wiring up the context.
+     */
+    if (returnValue instanceof EntityProxy) {
+      @SuppressWarnings("unchecked")
+      T toReturn = (T) context.edit((EntityProxy) returnValue);
+      return toReturn;
+    }
+
+    /*
+     * We're returning some object that's not an EntityProxy, most likely a
+     * Collection type. At the very least, propagate the current RequestContext
+     * so that editable chains can be constructed.
+     */
+    AutoBean<T> otherBean = AutoBeanUtils.getAutoBean(returnValue);
+    if (otherBean != null) {
+      otherBean.setTag(EntityProxyCategory.REQUEST_CONTEXT,
+          bean.getTag(EntityProxyCategory.REQUEST_CONTEXT));
+    }
+    return returnValue;
   }
 }
diff --git a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
index 2b4f723..158331b 100644
--- a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
@@ -1762,6 +1762,10 @@
       @Override
       public void onSuccess(SimpleFooProxy response) {
         assertEquals(2, response.getOneToManyField().size());
+        
+        // Check lists of proxies returned from a mutable object are mutable
+        response = simpleFooRequest().edit(response);
+        response.getOneToManyField().get(0).setUserName("canMutate");
         finishTestAndReset();
       }
     });