Revision: 8755
Author: [email protected]
Date: Fri Sep 10 13:31:52 2010
Log: Fixed the firing of events on changes to EntityProxy. Added an ACQUIRE event and implemented the copy-on-write semantics.

Patch by: amitmanjhi
Review by: rjrjr (desk review)

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

http://code.google.com/p/google-web-toolkit/source/detail?r=8755

Added:
/trunk/user/test/com/google/gwt/requestfactory/client/impl/ValueStoreJsonImplTest.java
Modified:
/trunk/user/src/com/google/gwt/requestfactory/client/impl/AbstractJsonObjectRequest.java /trunk/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequest.java /trunk/user/src/com/google/gwt/requestfactory/client/impl/DeltaValueStoreJsonImpl.java
 /trunk/user/src/com/google/gwt/requestfactory/client/impl/ProxyJsoImpl.java
/trunk/user/src/com/google/gwt/requestfactory/client/impl/ValueStoreJsonImpl.java
 /trunk/user/src/com/google/gwt/requestfactory/shared/Receiver.java
 /trunk/user/src/com/google/gwt/requestfactory/shared/WriteOperation.java
 /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
/trunk/user/test/com/google/gwt/requestfactory/client/impl/DeltaValueStoreJsonImplTest.java /trunk/user/test/com/google/gwt/requestfactory/client/impl/ProxyJsoImplTest.java

=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/requestfactory/client/impl/ValueStoreJsonImplTest.java Fri Sep 10 13:31:52 2010
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed 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 com.google.gwt.requestfactory.client.impl;
+
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Tests for {...@link ValueStoreJsonImpl}.
+ */
+public class ValueStoreJsonImplTest extends GWTTestCase {
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.requestfactory.RequestFactorySuite";
+  }
+
+  public void testPutInValueStore() {
+    ValueStoreJsonImpl valueStore = new ValueStoreJsonImpl();
+    ProxyJsoImpl minimalJso = ProxyJsoImplTest.getMinimalJso();
+    ProxyJsoImpl populatedJso = ProxyJsoImplTest.getPopulatedJso();
+    ProxyJsoImpl copyPopulatedJso = ProxyJsoImplTest.getPopulatedJso();
+    HandlerManager eventBus = new HandlerManager(null);
+    minimalJso.getRequestFactory().init(eventBus);
+
+    assertNull(valueStore.putInValueStore(minimalJso));
+    assertNull(valueStore.putInValueStore(populatedJso));
+    assertSame(populatedJso, valueStore.putInValueStore(copyPopulatedJso));
+    assertSame(populatedJso, valueStore.putInValueStore(minimalJso));
+  }
+
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/AbstractJsonObjectRequest.java Tue Sep 7 10:09:37 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/AbstractJsonObjectRequest.java Fri Sep 10 13:31:52 2010
@@ -49,7 +49,10 @@
     JavaScriptObject rawJso = (JavaScriptObject) result;
     ProxyJsoImpl jso = ProxyJsoImpl.create(rawJso, schema, requestFactory);

-    requestFactory.getValueStore().setProxy(jso);
+ ProxyJsoImpl oldJso = requestFactory.getValueStore().putInValueStore(jso);
+    if (oldJso != null) {
+      jso = oldJso;
+    }

     /*
      * schema really should be ProxySchema<? extends T>, and then this cast
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequest.java Tue Sep 7 10:09:37 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequest.java Fri Sep 10 13:31:52 2010
@@ -104,9 +104,12 @@
   public boolean isChanged() {
     return deltaValueStore.isChanged();
   }
-
+
+  /*
+   * used from the JSNI method processRelated.
+   */
   public void pushToValueStore(String schemaToken, JavaScriptObject jso) {
-    requestFactory.getValueStore().setProxy(
+    requestFactory.getValueStore().putInValueStore(
         ProxyJsoImpl.create(jso, requestFactory.getSchema(schemaToken),
             requestFactory));
   }
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/DeltaValueStoreJsonImpl.java Fri Sep 10 09:06:14 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/DeltaValueStoreJsonImpl.java Fri Sep 10 13:31:52 2010
@@ -228,13 +228,17 @@
           ProxyJsoImpl masterRecord = master.records.get(key);
           ProxyJsoImpl value = updates.get(key);
           if (masterRecord != null && value != null) {
-            // no support for partial updates.
- // TODO(amitmanjhi): instead of merging, get updates from server.
-            masterRecord.merge(value);
+            /*
+             * Currently, no support for partial updates. When the updates
+ * return all fields that have changed (the version number can be
+             * used to optimize the payload), it will fix partial updates.
+             */
+            copy.merge(masterRecord);
+            copy.merge(value);
             toRemove.add(key);
           }
           if (masterRecord != null) {
-            syncResults.add(makeSyncResult(masterRecord, null, null));
+            syncResults.add(makeSyncResult(copy, null, null));
           } else {
             // do not change the masterRecord or fire event
             syncResults.add(makeSyncResult(copy, null, null));
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/ProxyJsoImpl.java Fri Sep 10 09:06:14 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/ProxyJsoImpl.java Fri Sep 10 13:31:52 2010
@@ -334,6 +334,22 @@
     return rtn;
   }-*/;

+  final boolean hasChanged(ProxyJsoImpl newJso) {
+    assert getSchema() == newJso.getSchema();
+    for (Property<?> property : getSchema().allProperties()) {
+      if (newJso.isDefined(property.getName())) {
+        if (isDefined(property.getName())) {
+          if (hasValueChanged(property.getName(), newJso)) {
+            return true;
+          }
+        } else {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
private native boolean copyPropertyIfDifferent(String name, ProxyJsoImpl from) /*-{
     if (this[name] == from[name]) {
       return false;
@@ -358,6 +374,13 @@
     return this[name];
   }-*/;

+ private native boolean hasValueChanged(String name, ProxyJsoImpl from) /*-{
+    if (this[name] == from[name]) {
+      return false;
+    }
+    return true;
+  }-*/;
+
   private native void setBoolean(String name, boolean value) /*-{
     this[name] = value;
   }-*/;
@@ -374,12 +397,12 @@
     this[name] = null;
   }-*/;

-  private final native void setRequestFactory(
+  private native void setRequestFactory(
       RequestFactoryJsonImpl requestFactory) /*-{
     this['__rf'] = requestFactory;
   }-*/;

-  private final native void setSchema(ProxySchema<?> schema) /*-{
+  private native void setSchema(ProxySchema<?> schema) /*-{
     this['__key'] = schema;
   }-*/;

=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/ValueStoreJsonImpl.java Wed Sep 8 11:08:25 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/ValueStoreJsonImpl.java Fri Sep 10 13:31:52 2010
@@ -45,19 +45,15 @@
     return schema.create(records.get(key));
   }

-  void setProxy(ProxyJsoImpl newRecord) {
-    setRecordInList(newRecord, 0, null);
-  }
-
-  void setRecords(JsArray<ProxyJsoImpl> newRecords) {
-    for (int i = 0, l = newRecords.length(); i < l; i++) {
-      ProxyJsoImpl newRecord = newRecords.get(i);
-      setRecordInList(newRecord, i, newRecords);
-    }
-  }
-
-  private void setRecordInList(ProxyJsoImpl newJsoRecord, int i,
-      JsArray<ProxyJsoImpl> array) {
+  /**
+   * Puts a {...@link ProxyJsoImpl} newJsoRecord in the valueStore following a
+ * copy-on-write scheme, and sends appropriate events. If the valuestore had a + * Jso that was the same or a superset of newJsoRecord, returns the valuestore
+   * jso. Otherwise, puts newJsoRecord in the valuestore and returns null.
+   * <p>
+   * package-protected for testing purposes.
+   */
+  ProxyJsoImpl putInValueStore(ProxyJsoImpl newJsoRecord) {
EntityProxyIdImpl recordKey = new EntityProxyIdImpl(newJsoRecord.getId(),
         newJsoRecord.getSchema(), RequestFactoryJsonImpl.NOT_FUTURE,
         newJsoRecord.getRequestFactory().datastoreToFutureMap.get(
@@ -66,19 +62,24 @@
     ProxyJsoImpl oldRecord = records.get(recordKey);
     if (oldRecord == null) {
       records.put(recordKey, newJsoRecord);
-      // TODO: need to fire a create event.
-    } else {
- // TODO: Merging is not the correct thing to do but it works as long as we - // don't have filtering by properties. Need to revisit this once response
-      // only has a subset of all properties.
-      boolean changed = oldRecord.merge(newJsoRecord);
-      newJsoRecord = oldRecord.cast();
-      if (array != null) {
-        array.set(i, newJsoRecord);
-      }
-      if (changed) {
-        newJsoRecord.getRequestFactory().postChangeEvent(newJsoRecord,
-            WriteOperation.UPDATE);
+      newJsoRecord.getRequestFactory().postChangeEvent(newJsoRecord,
+          WriteOperation.ACQUIRE);
+      return null;
+    }
+    if (oldRecord.hasChanged(newJsoRecord)) {
+      records.put(recordKey, newJsoRecord);
+      newJsoRecord.getRequestFactory().postChangeEvent(newJsoRecord,
+          WriteOperation.UPDATE);
+      return null;
+    }
+    return oldRecord;
+  }
+
+  void setRecords(JsArray<ProxyJsoImpl> newRecords) {
+    for (int i = 0, l = newRecords.length(); i < l; i++) {
+      ProxyJsoImpl oldRecord = putInValueStore(newRecords.get(i));
+      if (oldRecord != null) {
+        newRecords.set(i, oldRecord);
       }
     }
   }
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/Receiver.java Wed Aug 25 17:41:41 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/shared/Receiver.java Fri Sep 10 13:31:52 2010
@@ -15,7 +15,6 @@
  */
 package com.google.gwt.requestfactory.shared;

-
 import java.util.Set;

 /**
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/WriteOperation.java Fri Sep 10 06:27:47 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/shared/WriteOperation.java Fri Sep 10 13:31:52 2010
@@ -21,9 +21,10 @@
  * development, and is very likely to be deleted. Use it at your own risk.
  * </span>
  * </p>
- * The write operation enum used in DeltaValueStore.
+ * The write operation enum used in {...@link EntityProxyChangedEvent}.
  */
 public enum WriteOperation {
+  ACQUIRE("ACQUIRE"),
   CREATE("CREATE"),
   UPDATE("UPDATE"),
   DELETE("DELETE");
=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java Thu Sep 2 20:54:55 2010 +++ /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java Fri Sep 10 13:31:52 2010
@@ -20,6 +20,7 @@
 import com.google.gwt.requestfactory.client.RequestFactoryTest;
import com.google.gwt.requestfactory.client.impl.DeltaValueStoreJsonImplTest;
 import com.google.gwt.requestfactory.client.impl.ProxyJsoImplTest;
+import com.google.gwt.requestfactory.client.impl.ValueStoreJsonImplTest;

 import junit.framework.Test;

@@ -32,6 +33,7 @@
         "Test suite for requestfactory gwt code.");
     suite.addTestSuite(EditorTest.class);
     suite.addTestSuite(ProxyJsoImplTest.class);
+    suite.addTestSuite(ValueStoreJsonImplTest.class);
     suite.addTestSuite(DeltaValueStoreJsonImplTest.class);
     suite.addTestSuite(RequestFactoryTest.class);
     return suite;
=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/client/impl/DeltaValueStoreJsonImplTest.java Fri Sep 10 06:27:47 2010 +++ /trunk/user/test/com/google/gwt/requestfactory/client/impl/DeltaValueStoreJsonImplTest.java Fri Sep 10 13:31:52 2010
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.requestfactory.client.impl;

+import com.google.gwt.event.shared.HandlerManager;
 import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONParser;
@@ -58,11 +59,12 @@
   public void gwtSetUp() {
     valueStore = new ValueStoreJsonImpl();
requestFactory = (RequestFactoryJsonImpl) SimpleRequestFactoryInstance.factory();
+    HandlerManager eventBus = new HandlerManager(null);
+    requestFactory.init(eventBus);

     // add a proxy
jso = ProxyJsoImpl.create(42L, 1, SimpleRequestFactoryInstance.schema(),
         SimpleRequestFactoryInstance.impl());
-
     jso.set(SimpleFooProxy.userName, "bovik");
     jso.set(SimpleFooProxy.password, "bovik");
     jso.set(SimpleFooProxy.intId, 4);
@@ -70,7 +72,7 @@
     jso.set(SimpleFooProxy.boolField, false);
     jso.set(SimpleFooProxy.otherBoolField, true);

-    valueStore.setProxy(jso);
+    valueStore.putInValueStore(jso);
   }

   public void testCreate() {
@@ -143,7 +145,7 @@

     ProxyImpl mockProxy = new ProxyImpl(ProxyJsoImpl.create(futureId, 1,
SimpleRequestFactoryInstance.schema(), SimpleRequestFactoryInstance.impl()), RequestFactoryJsonImpl.NOT_FUTURE);
-    valueStore.setProxy(mockProxy.asJso()); // marked as non-future..
+ valueStore.putInValueStore(mockProxy.asJso()); // marked as non-future..
     DeltaValueStoreJsonImpl deltaValueStore = new DeltaValueStoreJsonImpl(
         valueStore, requestFactory);

=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/client/impl/ProxyJsoImplTest.java Tue Sep 7 10:09:37 2010 +++ /trunk/user/test/com/google/gwt/requestfactory/client/impl/ProxyJsoImplTest.java Fri Sep 10 13:31:52 2010
@@ -80,6 +80,20 @@
private static final String ID_VERSION_JSON = "{\"id\":\"42\",\"version\":1}"; private static final String ID_VERSION_JSON2 = "{\"id\":\"43\",\"version\":1}";

+  static ProxyJsoImpl getMinimalJso() {
+ return ProxyJsoImpl.create(42L, 1, SimpleRequestFactoryInstance.schema(),
+        SimpleRequestFactoryInstance.impl());
+  }
+
+  static ProxyJsoImpl getPopulatedJso() {
+    ProxyJsoImpl jso = getMinimalJso();
+    jso.set(SimpleFooProxy.userName, "bovik");
+    jso.set(SimpleFooProxy.password, "bovik");
+    jso.set(SimpleFooProxy.intId, 4);
+    jso.set(SimpleFooProxy.created, new Date(400));
+    return jso;
+  }
+
   @Override
   public String getModuleName() {
     return "com.google.gwt.requestfactory.RequestFactorySuite";
@@ -89,22 +103,29 @@
     ProxyJsoImpl emptyCopy = ProxyJsoImpl.emptyCopy(getPopulatedJso());
     testMinimalJso(emptyCopy);
   }
-
-  private native JavaScriptObject jsEval(String json) /*-{
-    eval("xyz=" + json);
-    return xyz;
-  }-*/;
-
-  private ProxyJsoImpl eval(String json) {
-    JavaScriptObject rawJso = jsEval(json);
- return ProxyJsoImpl.create(rawJso, SimpleRequestFactoryInstance.schema(),
-        SimpleRequestFactoryInstance.impl());
-  }

   public void testFromJson() {
     testMinimalJso(eval(ID_VERSION_JSON));
     testPopulatedJso(eval(ALL_PROPERTIES_JSON));
   }
+
+  /*
+   * TODO(amitmanjhi): test null values.
+   */
+  public void testHasChanged() {
+    ProxyJsoImpl minimalJso = getMinimalJso();
+    ProxyJsoImpl populatedJso = getPopulatedJso();
+    assertFalse(minimalJso.hasChanged(minimalJso));
+    assertFalse(populatedJso.hasChanged(populatedJso));
+
+    assertTrue(minimalJso.hasChanged(populatedJso));
+    assertFalse(populatedJso.hasChanged(minimalJso));
+
+    ProxyJsoImpl minimalJsoCopy = getMinimalJso();
+    assertFalse(minimalJso.hasChanged(minimalJsoCopy));
+    minimalJsoCopy.set(SimpleFooProxy.id, minimalJso.getId() + 42);
+    assertTrue(minimalJso.hasChanged(minimalJsoCopy));
+  }

   public void testIsEmpty() {
     assertTrue(getMinimalJso().isEmpty());
@@ -144,19 +165,16 @@
     assertEquals(ID_VERSION_JSON, getMinimalJso().toJson());
   }

-  private ProxyJsoImpl getMinimalJso() {
- return ProxyJsoImpl.create(42L, 1, SimpleRequestFactoryInstance.schema(),
+  private ProxyJsoImpl eval(String json) {
+    JavaScriptObject rawJso = jsEval(json);
+ return ProxyJsoImpl.create(rawJso, SimpleRequestFactoryInstance.schema(),
         SimpleRequestFactoryInstance.impl());
   }

-  private ProxyJsoImpl getPopulatedJso() {
-    ProxyJsoImpl jso = getMinimalJso();
-    jso.set(SimpleFooProxy.userName, "bovik");
-    jso.set(SimpleFooProxy.password, "bovik");
-    jso.set(SimpleFooProxy.intId, 4);
-    jso.set(SimpleFooProxy.created, new Date(400));
-    return jso;
-  }
+  private native JavaScriptObject jsEval(String json) /*-{
+    eval("xyz=" + json);
+    return xyz;
+  }-*/;

   private void testEmptyJso(JavaScriptObject rawJso) {
     ProxyJsoImpl jso = ProxyJsoImpl.create(rawJso, null, null);

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to