]> source.dussan.org Git - vaadin-framework.git/commitdiff
Use key mapping to keep track of data on the client-side
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Mon, 1 Feb 2016 15:44:56 +0000 (17:44 +0200)
committerTeemu Suo-Anttila <teemusa@vaadin.com>
Tue, 2 Feb 2016 17:38:38 +0000 (19:38 +0200)
This method fixes data removing to be based on the key mapping instead
of data content. Also the data clean up is now properly called when
dropping data objects.

Change-Id: I76a917968026f6c3b2693b52848448de92145fb1

client/src/com/vaadin/client/connectors/data/typed/DataSourceConnector.java
server/src/com/vaadin/server/communication/data/typed/DataProvider.java
shared/src/com/vaadin/shared/data/DataProviderClientRpc.java

index a2fc1db8e63521a64006492315076e7c0810189f..59d72baa6765f58e5efd5c963f38eed4660be08a 100644 (file)
  */
 package com.vaadin.client.connectors.data.typed;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.vaadin.client.ServerConnector;
 import com.vaadin.client.data.HasDataSource;
 import com.vaadin.client.extensions.AbstractExtensionConnector;
 import com.vaadin.client.widget.grid.datasources.ListDataSource;
 import com.vaadin.server.communication.data.typed.DataProvider;
 import com.vaadin.shared.data.DataProviderClientRpc;
+import com.vaadin.shared.data.DataProviderConstants;
+import com.vaadin.shared.data.DataRequestRpc;
 import com.vaadin.shared.ui.Connect;
 
+import elemental.json.Json;
 import elemental.json.JsonArray;
 import elemental.json.JsonObject;
 
 /**
- * A simple connector for DataProvider class.
+ * A simple connector for DataProvider class. Based on {@link ListDataSource}
+ * and does not support lazy loading or paging.
  * 
  * @since
  */
 @Connect(DataProvider.class)
 public class DataSourceConnector extends AbstractExtensionConnector {
 
-    ListDataSource<JsonObject> ds = new ListDataSource<JsonObject>();
+    private Map<String, JsonObject> keyToJson = new HashMap<String, JsonObject>();
+    private Set<String> droppedKeys = new HashSet<String>();
+    private ListDataSource<JsonObject> ds = new ListDataSource<JsonObject>();
+    private boolean pendingDrop = false;
 
     @Override
     protected void extend(ServerConnector target) {
@@ -44,8 +57,12 @@ public class DataSourceConnector extends AbstractExtensionConnector {
 
             @Override
             public void resetSize(long size) {
-                // Server will provide the data we need.
                 ds.asList().clear();
+                // Inform the server-side that all keys are now dropped.
+                for (String key : keyToJson.keySet()) {
+                    dropKey(key);
+                }
+                sendDroppedKeys();
             }
 
             @Override
@@ -54,12 +71,17 @@ public class DataSourceConnector extends AbstractExtensionConnector {
                 assert firstIndex <= l.size() : "Gap in data. First Index: "
                         + firstIndex + ", Size: " + l.size();
                 for (long i = 0; i < data.length(); ++i) {
+                    JsonObject object = data.getObject((int) i);
                     if (i + firstIndex == l.size()) {
-                        l.add(data.getObject((int) i));
+                        l.add(object);
                     } else if (i + firstIndex < l.size()) {
-                        l.set((int) (i + firstIndex), data.getObject((int) i));
+                        int index = (int) (i + firstIndex);
+                        dropKey(getKey(l.get(index)));
+                        l.set(index, object);
                     }
+                    keyToJson.put(getKey(object), object);
                 }
+                sendDroppedKeys();
             }
 
             @Override
@@ -68,13 +90,11 @@ public class DataSourceConnector extends AbstractExtensionConnector {
             }
 
             @Override
-            public void drop(JsonObject dataObject) {
-                List<JsonObject> l = ds.asList();
-                for (int i = 0; i < l.size(); ++i) {
-                    if (l.get(i).toJson().equals(dataObject.toJson())) {
-                        l.remove(i);
-                        return;
-                    }
+            public void drop(String key) {
+                if (keyToJson.containsKey(key)) {
+                    ds.asList().remove(keyToJson.get(key));
+                    dropKey(key);
+                    sendDroppedKeys();
                 }
             }
         });
@@ -86,4 +106,68 @@ public class DataSourceConnector extends AbstractExtensionConnector {
             assert false : "Parent not implementing HasDataSource";
         }
     }
+
+    /**
+     * Marks a key as dropped. Call to
+     * {@link DataSourceConnector#sendDroppedKeys()} should be called to make
+     * sure the information is sent to the server-side.
+     * 
+     * @param key
+     *            dropped key
+     */
+    private void dropKey(String key) {
+        if (keyToJson.containsKey(key)) {
+            droppedKeys.add(key);
+            keyToJson.remove(key);
+        }
+    }
+
+    /**
+     * Sends dropped keys to the server-side with a deferred scheduled command.
+     * Multiple calls to this method will only result to one command being
+     * executed.
+     */
+    private void sendDroppedKeys() {
+        if (pendingDrop) {
+            return;
+        }
+
+        pendingDrop = true;
+        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
+            @Override
+            public void execute() {
+                pendingDrop = false;
+                if (droppedKeys.isEmpty()) {
+                    return;
+                }
+
+                JsonArray keyArray = Json.createArray();
+                int i = 0;
+                for (String key : droppedKeys) {
+                    keyArray.set(i++, key);
+                }
+
+                getRpcProxy(DataRequestRpc.class).dropRows(keyArray);
+
+                // Force RPC since it's delayed.
+                getConnection().getServerRpcQueue().flush();
+
+                droppedKeys.clear();
+            }
+        });
+    }
+
+    /**
+     * Gets the mapping key from given {@link JsonObject}.
+     * 
+     * @param jsonObject
+     *            json object to get the key from
+     */
+    protected String getKey(JsonObject jsonObject) {
+        if (jsonObject.hasKey(DataProviderConstants.KEY)) {
+            return jsonObject.getString(DataProviderConstants.KEY);
+        }
+        return null;
+    }
 }
index a4e937cbdbae75d4009e50065b316adc6be49011..e9757927135d320bc47cf1a5f9144a42541b97d7 100644 (file)
@@ -187,8 +187,13 @@ public class DataProvider<T> extends AbstractExtension {
         }
 
         @Override
-        public void dropRows(JsonArray rowKeys) {
-            // FIXME: What should I do with these?
+        public void dropRows(JsonArray keys) {
+            for (int i = 0; i < keys.length(); ++i) {
+                handler.dropActiveData(keys.getString(i));
+            }
+
+            // Use the whole data as the ones sent to the client.
+            handler.cleanUp(data);
         }
     }
 
@@ -328,24 +333,26 @@ public class DataProvider<T> extends AbstractExtension {
     }
 
     /**
-     * Informs the DataProvider that an item has been added. It is assumed to be
-     * the last item in the collection.
+     * Informs the DataProvider that a data object has been added. It is assumed
+     * to be the last object in the collection.
      * 
-     * @param item
-     *            item added to collection
+     * @param data
+     *            data object added to collection
      */
-    public void add(T item) {
-        rpc.add(getDataObject(item));
+    public void add(T data) {
+        rpc.add(getDataObject(data));
     }
 
     /**
-     * Informs the DataProvider that an item has been removed.
+     * Informs the DataProvider that a data object has been removed.
      * 
-     * @param item
-     *            item removed from collection
+     * @param data
+     *            data object removed from collection
      */
-    public void remove(T item) {
-        rpc.drop(getDataObject(item));
+    public void remove(T data) {
+        if (handler.getActiveData().contains(data)) {
+            rpc.drop(getKeyMapper().key(data));
+        }
     }
 
 }
index de23e1c3eda17457909b5894adfe6d219e2a1bb3..c96a2a64fab863409673fa0570e5cb5b68796f73 100644 (file)
@@ -59,11 +59,11 @@ public interface DataProviderClientRpc extends ClientRpc {
     void add(JsonObject dataObject);
 
     /**
-     * Removes data from the client-side DataSource.
+     * Removes data identified by given key from the client-side DataSource.
      * 
-     * @param dataObject
-     *            single removed data object
+     * @param key
+     *            key identifying the object to be removed
      */
-    void drop(JsonObject dataObject);
+    void drop(String key);
 
 }