]> source.dussan.org Git - vaadin-framework.git/commitdiff
Make RpcDataProviderExtension more generic (#19266) feature/combobox-communication
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Wed, 18 Nov 2015 11:35:05 +0000 (12:35 +0100)
committerTeemu Suo-Anttila <teemusa@vaadin.com>
Wed, 18 Nov 2015 14:42:21 +0000 (15:42 +0100)
Change-Id: I3099f2568b70670248983f735aa6cbac46238b34

client/src/com/vaadin/client/connectors/GridConnector.java
client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java
client/src/com/vaadin/client/data/HasDataSource.java [new file with mode: 0644]
server/src/com/vaadin/server/communication/data/RpcDataProviderExtension.java
server/src/com/vaadin/ui/Grid.java

index 336469139ccbf060f097e61e81ee64e772bbb958..260a726c00318520ecd976fff3e96a46ba4a69f8 100644 (file)
@@ -47,6 +47,8 @@ import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
 import com.vaadin.client.connectors.RpcDataSourceConnector.DetailsListener;
 import com.vaadin.client.connectors.RpcDataSourceConnector.RpcDataSource;
+import com.vaadin.client.data.DataSource;
+import com.vaadin.client.data.HasDataSource;
 import com.vaadin.client.ui.AbstractFieldConnector;
 import com.vaadin.client.ui.AbstractHasComponentsConnector;
 import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
@@ -109,7 +111,7 @@ import elemental.json.JsonValue;
  */
 @Connect(com.vaadin.ui.Grid.class)
 public class GridConnector extends AbstractHasComponentsConnector implements
-        SimpleManagedLayout, DeferredWorker {
+        SimpleManagedLayout, DeferredWorker, HasDataSource<JsonObject> {
 
     private static final class CustomStyleGenerator implements
             CellStyleGenerator<JsonObject>, RowStyleGenerator<JsonObject> {
@@ -1061,11 +1063,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
         }
     }
 
-    public void setDataSource(RpcDataSource dataSource) {
-        this.dataSource = dataSource;
-        getWidget().setDataSource(this.dataSource);
-    }
-
     private void onSortStateChange() {
         List<SortOrder> sortOrder = new ArrayList<SortOrder>();
 
@@ -1230,4 +1227,15 @@ public class GridConnector extends AbstractHasComponentsConnector implements
         return result.isEmpty() ? null : result;
     }
 
+    @Override
+    public void setDataSource(DataSource<JsonObject> ds) {
+        if (ds instanceof RpcDataSource) {
+            dataSource = (RpcDataSource) ds;
+            getWidget().setDataSource(dataSource);
+        } else {
+            throw new IllegalArgumentException(
+                    "Given DataSource is not RpcDataSource");
+        }
+    }
+
 }
index d744bbc1c791f97acefb9f4af3906221f9431c71..f9f10158edbb3c9ca14ee987656b0d7be7b90c0d 100644 (file)
@@ -22,6 +22,7 @@ import java.util.List;
 
 import com.vaadin.client.ServerConnector;
 import com.vaadin.client.data.AbstractRemoteDataSource;
+import com.vaadin.client.data.HasDataSource;
 import com.vaadin.client.extensions.AbstractExtensionConnector;
 import com.vaadin.shared.data.DataProviderRpc;
 import com.vaadin.shared.data.DataRequestRpc;
@@ -246,8 +247,16 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector {
 
     @Override
     protected void extend(ServerConnector target) {
-        GridConnector gridConnector = (GridConnector) target;
-        dataSource.setDetailsListener(gridConnector.getDetailsListener());
-        gridConnector.setDataSource(dataSource);
+        if (target instanceof HasDataSource) {
+            ((HasDataSource<JsonObject>) target).setDataSource(dataSource);
+        } else {
+            throw new IllegalArgumentException(
+                    "Parent connector does not implement HasDataSource");
+        }
+
+        if (target instanceof GridConnector) {
+            dataSource.setDetailsListener(((GridConnector) target)
+                    .getDetailsListener());
+        }
     }
 }
diff --git a/client/src/com/vaadin/client/data/HasDataSource.java b/client/src/com/vaadin/client/data/HasDataSource.java
new file mode 100644 (file)
index 0000000..97e52b2
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * 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.vaadin.client.data;
+
+/**
+ * Interface describing a class that supports setting a {@link DataSource}.
+ * 
+ * @since
+ */
+public interface HasDataSource<T> {
+
+    public void setDataSource(DataSource<T> ds);
+}
index fed31646f43bfec9a8653fed3f059906a0dbbf00..d9fe43afed99b08e4d06f1df951c878f2cc8f7f1 100644 (file)
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.vaadin.data.Container;
 import com.vaadin.data.Container.Indexed;
 import com.vaadin.data.Container.Indexed.ItemAddEvent;
 import com.vaadin.data.Container.Indexed.ItemRemoveEvent;
@@ -53,11 +52,8 @@ import elemental.json.JsonArray;
 import elemental.json.JsonObject;
 
 /**
- * Provides Vaadin server-side container data source to a
- * {@link com.vaadin.client.ui.grid.GridConnector}. This is currently
- * implemented as an Extension hardcoded to support a specific connector type.
- * This will be changed once framework support for something more flexible has
- * been implemented.
+ * Provides Vaadin server-side container data source to a connector implementing
+ * {@link com.vaadin.client.data.HasDataSource}.
  * 
  * @since 7.4
  * @author Vaadin Ltd
@@ -71,7 +67,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
      */
     private class ActiveItemHandler implements Serializable, DataGenerator {
 
-        private final Map<Object, GridValueChangeListener> activeItemMap = new HashMap<Object, GridValueChangeListener>();
+        private final Map<Object, DataProviderValueChangeListener> activeItemMap = new HashMap<Object, DataProviderValueChangeListener>();
         private final KeyMapper<Object> keyMapper = new KeyMapper<Object>();
         private final Set<Object> droppedItems = new HashSet<Object>();
 
@@ -87,8 +83,9 @@ public class RpcDataProviderExtension extends AbstractExtension {
         public void addActiveItems(Collection<?> itemIds) {
             for (Object itemId : itemIds) {
                 if (!activeItemMap.containsKey(itemId)) {
-                    activeItemMap.put(itemId, new GridValueChangeListener(
-                            itemId, container.getItem(itemId)));
+                    activeItemMap.put(itemId,
+                            new DataProviderValueChangeListener(itemId,
+                                    container.getItem(itemId)));
                 }
             }
 
@@ -125,8 +122,9 @@ public class RpcDataProviderExtension extends AbstractExtension {
          * 
          * @return collection of value change listeners
          */
-        public Collection<GridValueChangeListener> getValueChangeListeners() {
-            return new HashSet<GridValueChangeListener>(activeItemMap.values());
+        public Collection<DataProviderValueChangeListener> getValueChangeListeners() {
+            return new HashSet<DataProviderValueChangeListener>(
+                    activeItemMap.values());
         }
 
         @Override
@@ -137,7 +135,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
         @Override
         public void destroyData(Object itemId) {
             keyMapper.remove(itemId);
-            GridValueChangeListener removed = activeItemMap.remove(itemId);
+            DataProviderValueChangeListener removed = activeItemMap
+                    .remove(itemId);
 
             if (removed != null) {
                 removed.removeListener();
@@ -146,10 +145,9 @@ public class RpcDataProviderExtension extends AbstractExtension {
     }
 
     /**
-     * A class to listen to changes in property values in the Container added
-     * with {@link Grid#setContainerDatasource(Container.Indexed)}, and notifies
-     * the data source to update the client-side representation of the modified
-     * item.
+     * A class to listen to changes in property values in the Container, and
+     * notifies the data source to update the client-side representation of the
+     * modified item.
      * <p>
      * One instance of this class can (and should) be reused for all the
      * properties in an item, since this class will inform that the entire row
@@ -159,15 +157,13 @@ public class RpcDataProviderExtension extends AbstractExtension {
      * Since there's no Container-wide possibility to listen to any kind of
      * value changes, an instance of this class needs to be attached to each and
      * every Item's Property in the container.
-     * 
-     * @see Grid#addValueChangeListener(Container, Object, Object)
-     * @see Grid#valueChangeListeners
      */
-    private class GridValueChangeListener implements ValueChangeListener {
+    private class DataProviderValueChangeListener implements
+            ValueChangeListener {
         private final Object itemId;
         private final Item item;
 
-        public GridValueChangeListener(Object itemId, Item item) {
+        public DataProviderValueChangeListener(Object itemId, Item item) {
             /*
              * Using an assert instead of an exception throw, just to optimize
              * prematurely
@@ -176,7 +172,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
             this.itemId = itemId;
             this.item = item;
 
-            internalAddColumns(getGrid().getColumns());
+            internalAddProperties();
         }
 
         @Override
@@ -185,18 +181,22 @@ public class RpcDataProviderExtension extends AbstractExtension {
         }
 
         public void removeListener() {
-            removeColumns(getGrid().getColumns());
+            for (final Object propertyId : item.getItemPropertyIds()) {
+                Property<?> property = item.getItemProperty(propertyId);
+                if (property instanceof ValueChangeNotifier) {
+                    ((ValueChangeNotifier) property)
+                            .removeValueChangeListener(this);
+                }
+            }
         }
 
         public void addColumns(Collection<Column> addedColumns) {
-            internalAddColumns(addedColumns);
             updateRowData(itemId);
         }
 
-        private void internalAddColumns(Collection<Column> addedColumns) {
-            for (final Column column : addedColumns) {
-                final Property<?> property = item.getItemProperty(column
-                        .getPropertyId());
+        private void internalAddProperties() {
+            for (final Object propertyId : item.getItemPropertyIds()) {
+                Property<?> property = item.getItemProperty(propertyId);
                 if (property instanceof ValueChangeNotifier) {
                     ((ValueChangeNotifier) property)
                             .addValueChangeListener(this);
@@ -205,14 +205,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
         }
 
         public void removeColumns(Collection<Column> removedColumns) {
-            for (final Column column : removedColumns) {
-                final Property<?> property = item.getItemProperty(column
-                        .getPropertyId());
-                if (property instanceof ValueChangeNotifier) {
-                    ((ValueChangeNotifier) property)
-                            .removeValueChangeListener(this);
-                }
-            }
+
         }
     }
 
@@ -310,11 +303,10 @@ public class RpcDataProviderExtension extends AbstractExtension {
     public void beforeClientResponse(boolean initial) {
         if (initial || bareItemSetTriggeredSizeChange) {
             /*
-             * Push initial set of rows, assuming Grid will initially be
-             * rendered scrolled to the top and with a decent amount of rows
-             * visible. If this guess is right, initial data can be shown
-             * without a round-trip and if it's wrong, the data will simply be
-             * discarded.
+             * Push initial set of rows, assuming the component will initially
+             * be rendering the first items in DataSource. If this guess is
+             * right, initial data can be shown without a round-trip and if it's
+             * wrong, the data will simply be discarded.
              */
             int size = container.size();
             rpc.resetDataAndSize(size);
@@ -369,15 +361,14 @@ public class RpcDataProviderExtension extends AbstractExtension {
 
             Item item = container.getItem(itemId);
 
-            rows.set(i, getRowData(getGrid().getColumns(), itemId, item));
+            rows.set(i, getRowData(itemId, item));
         }
         rpc.setRowData(firstRowToPush, rows);
 
         activeItemHandler.addActiveItems(itemIds);
     }
 
-    private JsonObject getRowData(Collection<Column> columns, Object itemId,
-            Item item) {
+    private JsonObject getRowData(Object itemId, Item item) {
 
         final JsonObject rowObject = Json.createObject();
         for (DataGenerator dg : dataGenerators) {
@@ -499,14 +490,13 @@ public class RpcDataProviderExtension extends AbstractExtension {
             return;
         }
 
-        List<Column> columns = getGrid().getColumns();
         JsonArray rowData = Json.createArray();
         int i = 0;
         for (Object itemId : itemIds) {
             if (activeItemHandler.getActiveItemIds().contains(itemId)) {
                 Item item = container.getItem(itemId);
                 if (item != null) {
-                    JsonObject row = getRowData(columns, itemId, item);
+                    JsonObject row = getRowData(itemId, item);
                     rowData.set(i++, row);
                 }
             }
@@ -535,10 +525,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
                         .removeItemSetChangeListener(itemListener);
             }
 
-        } else if (!(parent instanceof Grid)) {
-            throw new IllegalStateException(
-                    "Grid is the only accepted parent type");
         }
+
         super.setParent(parent);
     }
 
@@ -556,44 +544,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
         }
     }
 
-    /**
-     * Informs this data provider that given columns have been removed from
-     * grid.
-     * 
-     * @param removedColumns
-     *            a list of removed columns
-     */
-    public void columnsRemoved(List<Column> removedColumns) {
-        for (GridValueChangeListener l : activeItemHandler
-                .getValueChangeListeners()) {
-            l.removeColumns(removedColumns);
-        }
-
-        // No need to resend unchanged data. Client will remember the old
-        // columns until next set of rows is sent.
-    }
-
-    /**
-     * Informs this data provider that given columns have been added to grid.
-     * 
-     * @param addedColumns
-     *            a list of added columns
-     */
-    public void columnsAdded(List<Column> addedColumns) {
-        for (GridValueChangeListener l : activeItemHandler
-                .getValueChangeListeners()) {
-            l.addColumns(addedColumns);
-        }
-
-        // Resend all rows to contain new data.
-        refreshCache();
-    }
-
     public KeyMapper<Object> getKeyMapper() {
         return activeItemHandler.keyMapper;
     }
-
-    protected Grid getGrid() {
-        return (Grid) getParent();
-    }
 }
index 0f3e634ed385a4fe31ccbbd0d67202e2db1b0a7b..6aa86f21ac6f5c4418cceaca07274f3783d1624f 100644 (file)
@@ -4405,29 +4405,22 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
                     .getContainerPropertyIds());
 
             // Find columns that need to be removed.
-            List<Column> removedColumns = new LinkedList<Column>();
-            for (Object propertyId : columns.keySet()) {
-                if (!properties.contains(propertyId)) {
-                    removedColumns.add(getColumn(propertyId));
-                }
-            }
+            List<Object> removedProperties = new LinkedList<Object>(
+                    columns.keySet());
+            removedProperties.removeAll(properties);
 
             // Actually remove columns.
-            for (Column column : removedColumns) {
-                Object propertyId = column.getPropertyId();
+            for (Object propertyId : removedProperties) {
                 internalRemoveColumn(propertyId);
                 columnKeys.remove(propertyId);
             }
-            datasourceExtension.columnsRemoved(removedColumns);
 
             // Add new columns
-            List<Column> addedColumns = new LinkedList<Column>();
             for (Object propertyId : properties) {
                 if (!columns.containsKey(propertyId)) {
-                    addedColumns.add(appendColumn(propertyId));
+                    appendColumn(propertyId);
                 }
             }
-            datasourceExtension.columnsAdded(addedColumns);
 
             if (getFrozenColumnCount() > columns.size()) {
                 setFrozenColumnCount(columns.size());
@@ -4444,6 +4437,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
                     }
                 }
             }
+
+            // Update all rows.
+            datasourceExtension.refreshCache();
         }
     };
 
@@ -4462,13 +4458,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
      */
     private SelectionModel selectionModel;
 
-    /**
-     * Used to know whether selection change events originate from the server or
-     * the client so the selection change handler knows whether the changes
-     * should be sent to the client.
-     */
-    private boolean applyingSelectionFromClient;
-
     private final Header header = new Header(this);
     private final Footer footer = new Footer(this);
 
@@ -5018,7 +5007,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         Column column = getColumn(propertyId);
         List<Column> addedColumns = new ArrayList<Column>();
         addedColumns.add(column);
-        datasourceExtension.columnsAdded(addedColumns);
+
+        datasourceExtension.refreshCache();
 
         return column;
     }
@@ -5082,12 +5072,10 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
      * Removes all columns from this Grid.
      */
     public void removeAllColumns() {
-        List<Column> removed = new ArrayList<Column>(columns.values());
         Set<Object> properties = new HashSet<Object>(columns.keySet());
         for (Object propertyId : properties) {
             removeColumn(propertyId);
         }
-        datasourceExtension.columnsRemoved(removed);
     }
 
     /**
@@ -5208,7 +5196,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         List<Column> removed = new ArrayList<Column>();
         removed.add(getColumn(propertyId));
         internalRemoveColumn(propertyId);
-        datasourceExtension.columnsRemoved(removed);
     }
 
     private void internalRemoveColumn(Object propertyId) {
@@ -5826,8 +5813,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
     }
 
     /**
-     * Gets the
-     * {@link KeyMapper } being used by the data source.
+     * Gets the {@link KeyMapper } being used by the data source.
      * 
      * @return the key mapper being used by the data source
      */