diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-11-18 12:35:05 +0100 |
---|---|---|
committer | Henri Sara <hesara@vaadin.com> | 2016-01-15 14:48:52 +0200 |
commit | f22eb521fb5d7778abccbec87d3996774a9ca752 (patch) | |
tree | 910913cf85498c8c7779e360012cb46a51bb9adf | |
parent | 029f3e59ef23625ef5171705e3fe1d54c7a531c7 (diff) | |
download | vaadin-framework-f22eb521fb5d7778abccbec87d3996774a9ca752.tar.gz vaadin-framework-f22eb521fb5d7778abccbec87d3996774a9ca752.zip |
Make RpcDataProviderExtension more generic (#19266)
Change-Id: I3099f2568b70670248983f735aa6cbac46238b34
5 files changed, 99 insertions, 118 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index 90d9d71088..1a50b905de 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -49,6 +49,8 @@ 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.ui.AbstractComponentConnector; +import com.vaadin.client.data.DataSource; +import com.vaadin.client.data.HasDataSource; import com.vaadin.client.ui.AbstractHasComponentsConnector; import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; import com.vaadin.client.ui.SimpleManagedLayout; @@ -110,7 +112,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> { @@ -1092,11 +1094,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>(); @@ -1279,4 +1276,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"); + } + } + } diff --git a/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java b/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java index d744bbc1c7..f9f10158ed 100644 --- a/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java +++ b/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java @@ -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 index 0000000000..97e52b2d94 --- /dev/null +++ b/client/src/com/vaadin/client/data/HasDataSource.java @@ -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); +} diff --git a/server/src/com/vaadin/server/communication/data/RpcDataProviderExtension.java b/server/src/com/vaadin/server/communication/data/RpcDataProviderExtension.java index 1b78ca4518..a6cecbb99d 100644 --- a/server/src/com/vaadin/server/communication/data/RpcDataProviderExtension.java +++ b/server/src/com/vaadin/server/communication/data/RpcDataProviderExtension.java @@ -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 @@ -141,7 +139,8 @@ public class RpcDataProviderExtension extends AbstractExtension { } private void removeListener(Object itemId) { - GridValueChangeListener removed = activeItemMap.remove(itemId); + DataProviderValueChangeListener removed = activeItemMap + .remove(itemId); if (removed != null) { removed.removeListener(); @@ -150,10 +149,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 @@ -163,15 +161,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 @@ -180,7 +176,7 @@ public class RpcDataProviderExtension extends AbstractExtension { this.itemId = itemId; this.item = item; - internalAddColumns(getGrid().getColumns()); + internalAddProperties(); } @Override @@ -189,18 +185,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); @@ -209,14 +209,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); - } - } + } } @@ -321,11 +314,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); @@ -380,15 +372,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) { @@ -511,14 +502,13 @@ public class RpcDataProviderExtension extends AbstractExtension { } Collection<Object> activeItemIds = activeItemHandler.getActiveItemIds(); - List<Column> columns = getGrid().getColumns(); JsonArray rowData = Json.createArray(); int i = 0; for (Object itemId : itemIds) { if (activeItemIds.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); } } @@ -547,10 +537,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); } @@ -568,44 +556,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(); - } } diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 0774afd582..10b5e84150 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -4423,29 +4423,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()); @@ -4462,6 +4455,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, } } } + + // Update all rows. + datasourceExtension.refreshCache(); } }; @@ -4480,13 +4476,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); @@ -5046,7 +5035,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; } @@ -5110,12 +5100,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); } /** @@ -5236,7 +5224,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) { |