Propagate WriteOperation.DELETE to EntityProxyChange handlers.
Re-enable a disabled test.
Patch by: bobv
Review by: rjrjr

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


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9378 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java b/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
index 91adc8c..3027693 100644
--- a/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
+++ b/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
@@ -114,7 +114,10 @@
   }
 
   private static final String PARENT_OBJECT = "parentObject";
-  private final Set<SimpleProxyId<?>> createdIds = new HashSet<SimpleProxyId<?>>();
+  private static final WriteOperation[] PERSIST_AND_UPDATE = {
+      WriteOperation.PERSIST, WriteOperation.UPDATE};
+  private static final WriteOperation[] DELETE_ONLY = {WriteOperation.DELETE};
+  private static final WriteOperation[] UPDATE_ONLY = {WriteOperation.UPDATE};
   private final List<AbstractRequest<?>> invocations = new ArrayList<AbstractRequest<?>>();
   private boolean locked;
   private final AbstractRequestFactory requestFactory;
@@ -149,7 +152,6 @@
     checkLocked();
 
     SimpleProxyId<T> id = requestFactory.allocateId(clazz);
-    createdIds.add(id);
     AutoBean<T> created = requestFactory.createProxy(clazz, id);
     return takeOwnership(created);
   }
@@ -612,7 +614,8 @@
         if (response.getGeneralFailure() != null) {
           ServerFailureMessage failure = response.getGeneralFailure();
           ServerFailure fail = new ServerFailure(failure.getMessage(),
-              failure.getExceptionType(), failure.getStackTrace(), failure.isFatal());
+              failure.getExceptionType(), failure.getStackTrace(),
+              failure.isFatal());
 
           fail(receiver, fail);
           return;
@@ -649,7 +652,8 @@
                 response.getInvocationResults().get(i)).as();
             invocations.get(i).onFail(
                 new ServerFailure(failure.getMessage(),
-                    failure.getExceptionType(), failure.getStackTrace(), failure.isFatal()));
+                    failure.getExceptionType(), failure.getStackTrace(),
+                    failure.isFatal()));
           }
         }
 
@@ -777,24 +781,36 @@
    * Process an array of OperationMessages.
    */
   private void processReturnOperations(ResponseMessage response) {
-    List<OperationMessage> records = response.getOperations();
+    List<OperationMessage> ops = response.getOperations();
 
     // If there are no observable effects, this will be null
-    if (records == null) {
+    if (ops == null) {
       return;
     }
 
-    for (OperationMessage op : records) {
+    for (OperationMessage op : ops) {
       SimpleProxyId<?> id = getId(op);
-      if (id.isEphemeral()) {
-        processReturnOperation(id, op);
-      } else if (id.wasEphemeral() && createdIds.contains(id)) {
-        // Only send a PERSIST if this RequestContext created the id.
-        processReturnOperation(id, op, WriteOperation.PERSIST,
-            WriteOperation.UPDATE);
-      } else {
-        processReturnOperation(id, op, WriteOperation.UPDATE);
+      WriteOperation[] toPropagate = null;
+
+      // May be null if the server is returning an unpersisted object
+      WriteOperation effect = op.getOperation();
+      if (effect != null) {
+        switch (effect) {
+          case DELETE:
+            toPropagate = DELETE_ONLY;
+            break;
+          case PERSIST:
+            toPropagate = PERSIST_AND_UPDATE;
+            break;
+          case UPDATE:
+            toPropagate = UPDATE_ONLY;
+            break;
+          default:
+            // Should never reach here
+            throw new RuntimeException(effect.toString());
+        }
       }
+      processReturnOperation(id, op, toPropagate);
     }
   }
 
diff --git a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
index c0c0955..8dec044 100644
--- a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
@@ -197,69 +197,6 @@
     }
   }
 
-  /**
-   * Test that removing a parent entity and implicitly removing the child sends
-   * an event to the client that the child was removed.
-   * 
-   * TODO(rjrjr): Should cascading deletes be detected?
-   */
-  public void disableTestMethodWithSideEffectDeleteChild() {
-    delayTestFinish(DELAY_TEST_FINISH);
-
-    // Persist bar.
-    SimpleBarRequest context = req.simpleBarRequest();
-    final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
-    context.persistAndReturnSelf().using(bar).fire(
-        new Receiver<SimpleBarProxy>() {
-          @Override
-          public void onSuccess(SimpleBarProxy persistentBar) {
-            persistentBar = checkSerialization(persistentBar);
-            // Persist foo with bar as a child.
-            SimpleFooRequest context = req.simpleFooRequest();
-            SimpleFooProxy foo = context.create(SimpleFooProxy.class);
-            final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
-                foo);
-            foo = context.edit(foo);
-            foo.setUserName("John");
-            foo.setBarField(bar);
-            persistRequest.fire(new Receiver<SimpleFooProxy>() {
-              @Override
-              public void onSuccess(SimpleFooProxy persistentFoo) {
-                persistentFoo = checkSerialization(persistentFoo);
-                // Handle changes to SimpleFooProxy.
-                final SimpleFooEventHandler<SimpleFooProxy> fooHandler = new SimpleFooEventHandler<SimpleFooProxy>();
-                EntityProxyChange.registerForProxyType(req.getEventBus(),
-                    SimpleFooProxy.class, fooHandler);
-
-                // Handle changes to SimpleBarProxy.
-                final SimpleFooEventHandler<SimpleBarProxy> barHandler = new SimpleFooEventHandler<SimpleBarProxy>();
-                EntityProxyChange.registerForProxyType(req.getEventBus(),
-                    SimpleBarProxy.class, barHandler);
-
-                // Delete bar.
-                SimpleFooRequest context = req.simpleFooRequest();
-                final Request<Void> deleteRequest = context.deleteBar().using(
-                    persistentFoo);
-                SimpleFooProxy editable = context.edit(persistentFoo);
-                editable.setBarField(bar);
-                deleteRequest.fire(new Receiver<Void>() {
-                  @Override
-                  public void onSuccess(Void response) {
-                    assertEquals(1, fooHandler.updateEventCount); // set bar to
-                    // null
-                    assertEquals(1, fooHandler.totalEventCount);
-
-                    assertEquals(1, barHandler.deleteEventCount); // deleted bar
-                    assertEquals(1, barHandler.totalEventCount);
-                    finishTestAndReset();
-                  }
-                });
-              }
-            });
-          }
-        });
-  }
-
   @Override
   public String getModuleName() {
     return "com.google.gwt.requestfactory.RequestFactorySuite";
@@ -810,6 +747,68 @@
     });
   }
 
+  /**
+   * Test that removing a parent entity and implicitly removing the child sends
+   * an event to the client that the child was removed.
+   */
+  public void testMethodWithSideEffectDeleteChild() {
+    delayTestFinish(DELAY_TEST_FINISH);
+
+    // Handle changes to SimpleFooProxy.
+    final SimpleFooEventHandler<SimpleFooProxy> fooHandler = new SimpleFooEventHandler<SimpleFooProxy>();
+    EntityProxyChange.registerForProxyType(req.getEventBus(),
+        SimpleFooProxy.class, fooHandler);
+
+    // Handle changes to SimpleBarProxy.
+    final SimpleFooEventHandler<SimpleBarProxy> barHandler = new SimpleFooEventHandler<SimpleBarProxy>();
+    EntityProxyChange.registerForProxyType(req.getEventBus(),
+        SimpleBarProxy.class, barHandler);
+
+    // Persist bar.
+    SimpleBarRequest context = req.simpleBarRequest();
+    final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
+    context.persistAndReturnSelf().using(bar).fire(
+        new Receiver<SimpleBarProxy>() {
+          @Override
+          public void onSuccess(SimpleBarProxy persistentBar) {
+            persistentBar = checkSerialization(persistentBar);
+            // Persist foo with bar as a child.
+            SimpleFooRequest context = req.simpleFooRequest();
+            SimpleFooProxy foo = context.create(SimpleFooProxy.class);
+            final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
+                foo).with("barField");
+            foo = context.edit(foo);
+            foo.setUserName("John");
+            foo.setBarField(bar);
+            persistRequest.fire(new Receiver<SimpleFooProxy>() {
+              @Override
+              public void onSuccess(SimpleFooProxy persistentFoo) {
+                persistentFoo = checkSerialization(persistentFoo);
+
+                // Delete bar.
+                SimpleFooRequest context = req.simpleFooRequest();
+                final Request<Void> deleteRequest = context.deleteBar().using(
+                    persistentFoo);
+                deleteRequest.fire(new Receiver<Void>() {
+                  @Override
+                  public void onSuccess(Void response) {
+                    assertEquals(1, fooHandler.persistEventCount);
+                    assertEquals(2, fooHandler.updateEventCount);
+                    assertEquals(3, fooHandler.totalEventCount);
+
+                    assertEquals(1, barHandler.persistEventCount);
+                    assertEquals(1, barHandler.updateEventCount);
+                    assertEquals(1, barHandler.deleteEventCount);
+                    assertEquals(3, barHandler.totalEventCount);
+                    finishTestAndReset();
+                  }
+                });
+              }
+            });
+          }
+        });
+  }
+
   /*
    * tests that (a) any method can have a side effect that is handled correctly.
    * (b) instance methods are handled correctly and (c) a request cannot be
@@ -1008,7 +1007,7 @@
    */
   public void testNullValueInIntegerListRequest() {
     delayTestFinish(DELAY_TEST_FINISH);
-    List<Integer> list = Arrays.asList(new Integer[] {1, 2, null});
+    List<Integer> list = Arrays.asList(new Integer[]{1, 2, null});
     final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInIntegerList(
         list);
     fooReq.fire(new Receiver<Void>() {
@@ -1024,7 +1023,7 @@
    */
   public void testNullValueInStringListRequest() {
     delayTestFinish(DELAY_TEST_FINISH);
-    List<String> list = Arrays.asList(new String[] {"nonnull", "null", null});
+    List<String> list = Arrays.asList(new String[]{"nonnull", "null", null});
     final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInStringList(
         list);
     fooReq.fire(new Receiver<Void>() {
@@ -1801,21 +1800,6 @@
     });
   }
 
-  public void testPrimitiveListBooleanAsParameter() {
-    delayTestFinish(DELAY_TEST_FINISH);
-
-    Request<Boolean> procReq = simpleFooRequest().processBooleanList(
-        Arrays.asList(true, false));
-
-    procReq.fire(new Receiver<Boolean>() {
-      @Override
-      public void onSuccess(Boolean response) {
-        assertEquals(true, (boolean) response);
-        finishTestAndReset();
-      }
-    });
-  }
-
   public void testPrimitiveListBigDecimalAsParameter() {
     delayTestFinish(DELAY_TEST_FINISH);
 
@@ -1856,6 +1840,21 @@
         });
   }
 
+  public void testPrimitiveListBooleanAsParameter() {
+    delayTestFinish(DELAY_TEST_FINISH);
+
+    Request<Boolean> procReq = simpleFooRequest().processBooleanList(
+        Arrays.asList(true, false));
+
+    procReq.fire(new Receiver<Boolean>() {
+      @Override
+      public void onSuccess(Boolean response) {
+        assertEquals(true, (boolean) response);
+        finishTestAndReset();
+      }
+    });
+  }
+
   @SuppressWarnings("deprecation")
   public void testPrimitiveListDateAsParameter() {
     delayTestFinish(DELAY_TEST_FINISH);
diff --git a/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java b/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
index 1ac5987..cd4f8d6 100644
--- a/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
+++ b/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
@@ -447,9 +447,11 @@
 
   public void deleteBar() {
     if (barField != null) {
+      isChanged = true;
       barField.delete();
     }
     barField = null;
+    persist();
   }
 
   public SimpleBar getBarField() {