aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <tsuoanttila@users.noreply.github.com>2017-01-25 12:27:44 +0200
committerDenis <denis@vaadin.com>2017-01-25 12:27:44 +0200
commit294ca0a2f5c29b65f9c4dc5887bfa0abc1cb7c7f (patch)
tree0a4630122dadc632e6508c85e4e79c717508de85 /server/src/main
parentbe694984fb35262b32c89be075e6d4a059931b62 (diff)
downloadvaadin-framework-294ca0a2f5c29b65f9c4dc5887bfa0abc1cb7c7f.tar.gz
vaadin-framework-294ca0a2f5c29b65f9c4dc5887bfa0abc1cb7c7f.zip
Add APIs to inform components of stale objects in DataProvider (#8271)
* Add DataProvider refreshItem for single item update * Add 'id' concept for DataProviders This patch also adds a simplified data provider that can replace items based on their id. This can be used to simulate stale objects from an actual backend. * Add refresh logic to Grid SelectionModels * Remove broken equals and hashCode * Refresh KeyMapper, clean up some methods * Fix UI.access in test * Fix tests and Grid single selection model * Do clean up before replacing data provider * Check correct variable for null value * Fix other selects, add generic tests * Code style fixes, removed assert * Merge remote-tracking branch 'origin/master' into 286_refresh_items * Fix documentation for refreshing an item * Improve introduction chapter, minor clarifications * Merge remote-tracking branch 'origin/master' into 287_refresh_items * Add missing parameters in unit tests
Diffstat (limited to 'server/src/main')
-rw-r--r--server/src/main/java/com/vaadin/data/provider/AbstractDataProvider.java13
-rw-r--r--server/src/main/java/com/vaadin/data/provider/BackEndDataProvider.java1
-rw-r--r--server/src/main/java/com/vaadin/data/provider/CallbackDataProvider.java42
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataChangeEvent.java50
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataCommunicator.java24
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataGenerator.java10
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataKeyMapper.java14
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataProvider.java29
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataProviderListener.java7
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataProviderWrapper.java13
-rw-r--r--server/src/main/java/com/vaadin/server/KeyMapper.java14
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java35
-rw-r--r--server/src/main/java/com/vaadin/ui/components/grid/MultiSelectionModelImpl.java35
-rw-r--r--server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java14
14 files changed, 267 insertions, 34 deletions
diff --git a/server/src/main/java/com/vaadin/data/provider/AbstractDataProvider.java b/server/src/main/java/com/vaadin/data/provider/AbstractDataProvider.java
index 3319bfb382..c87e18e1c2 100644
--- a/server/src/main/java/com/vaadin/data/provider/AbstractDataProvider.java
+++ b/server/src/main/java/com/vaadin/data/provider/AbstractDataProvider.java
@@ -18,6 +18,7 @@ package com.vaadin.data.provider;
import java.lang.reflect.Method;
import java.util.EventObject;
+import com.vaadin.data.provider.DataChangeEvent.DataRefreshEvent;
import com.vaadin.event.EventRouter;
import com.vaadin.shared.Registration;
@@ -39,14 +40,20 @@ public abstract class AbstractDataProvider<T, F> implements DataProvider<T, F> {
private EventRouter eventRouter;
@Override
- public Registration addDataProviderListener(DataProviderListener listener) {
+ public Registration addDataProviderListener(
+ DataProviderListener<T> listener) {
return addListener(DataChangeEvent.class, listener,
DataProviderListener.class.getMethods()[0]);
}
@Override
public void refreshAll() {
- fireEvent(new DataChangeEvent(this));
+ fireEvent(new DataChangeEvent<>(this));
+ }
+
+ @Override
+ public void refreshItem(T item) {
+ fireEvent(new DataRefreshEvent<>(this, item));
}
/**
@@ -65,7 +72,7 @@ public abstract class AbstractDataProvider<T, F> implements DataProvider<T, F> {
* @return a registration for the listener
*/
protected Registration addListener(Class<?> eventType,
- DataProviderListener listener, Method method) {
+ DataProviderListener<T> listener, Method method) {
if (eventRouter == null) {
eventRouter = new EventRouter();
}
diff --git a/server/src/main/java/com/vaadin/data/provider/BackEndDataProvider.java b/server/src/main/java/com/vaadin/data/provider/BackEndDataProvider.java
index 36d875a21a..b50b5c7fc8 100644
--- a/server/src/main/java/com/vaadin/data/provider/BackEndDataProvider.java
+++ b/server/src/main/java/com/vaadin/data/provider/BackEndDataProvider.java
@@ -71,5 +71,4 @@ public interface BackEndDataProvider<T, F> extends DataProvider<T, F> {
default boolean isInMemory() {
return false;
}
-
}
diff --git a/server/src/main/java/com/vaadin/data/provider/CallbackDataProvider.java b/server/src/main/java/com/vaadin/data/provider/CallbackDataProvider.java
index d83c1f1934..2f68e57e06 100644
--- a/server/src/main/java/com/vaadin/data/provider/CallbackDataProvider.java
+++ b/server/src/main/java/com/vaadin/data/provider/CallbackDataProvider.java
@@ -18,6 +18,7 @@ package com.vaadin.data.provider;
import java.util.Objects;
import java.util.stream.Stream;
+import com.vaadin.data.ValueProvider;
import com.vaadin.server.SerializableFunction;
import com.vaadin.server.SerializableToIntFunction;
@@ -36,6 +37,7 @@ public class CallbackDataProvider<T, F>
extends AbstractBackEndDataProvider<T, F> {
private final SerializableFunction<Query<T, F>, Stream<T>> fetchCallback;
private final SerializableToIntFunction<Query<T, F>> sizeCallback;
+ private final ValueProvider<T, Object> idGetter;
/**
* Constructs a new DataProvider to request data using callbacks for
@@ -45,16 +47,40 @@ public class CallbackDataProvider<T, F>
* function that returns a stream of items from the back end for
* a query
* @param sizeCallback
- * function that returns the number of items in the back end for
- * a query
+ * function that return the number of items in the back end for a
+ * query
+ *
+ * @see #CallbackDataProvider(SerializableFunction,
+ * SerializableToIntFunction, ValueProvider)
*/
public CallbackDataProvider(
SerializableFunction<Query<T, F>, Stream<T>> fetchCallback,
SerializableToIntFunction<Query<T, F>> sizeCallback) {
- Objects.requireNonNull(fetchCallback, "Request function can't be null");
+ this(fetchCallback, sizeCallback, t -> t);
+ }
+
+ /**
+ * Constructs a new DataProvider to request data using callbacks for
+ * fetching and counting items in the back end.
+ *
+ * @param fetchCallBack
+ * function that requests data from back end based on query
+ * @param sizeCallback
+ * function that returns the amount of data in back end for query
+ * @param identifierGetter
+ * function that returns the identifier for a given item
+ */
+ public CallbackDataProvider(
+ SerializableFunction<Query<T, F>, Stream<T>> fetchCallBack,
+ SerializableToIntFunction<Query<T, F>> sizeCallback,
+ ValueProvider<T, Object> identifierGetter) {
+ Objects.requireNonNull(fetchCallBack, "Request function can't be null");
Objects.requireNonNull(sizeCallback, "Size callback can't be null");
- this.fetchCallback = fetchCallback;
+ Objects.requireNonNull(identifierGetter,
+ "Identifier getter function can't be null");
+ this.fetchCallback = fetchCallBack;
this.sizeCallback = sizeCallback;
+ this.idGetter = identifierGetter;
}
@Override
@@ -66,4 +92,12 @@ public class CallbackDataProvider<T, F>
protected int sizeInBackEnd(Query<T, F> query) {
return sizeCallback.applyAsInt(query);
}
+
+ @Override
+ public Object getId(T item) {
+ Object itemId = idGetter.apply(item);
+ assert itemId != null : "CallbackDataProvider got null as an id for item: "
+ + item;
+ return itemId;
+ }
}
diff --git a/server/src/main/java/com/vaadin/data/provider/DataChangeEvent.java b/server/src/main/java/com/vaadin/data/provider/DataChangeEvent.java
index 86ad9235a6..93def4f810 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataChangeEvent.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataChangeEvent.java
@@ -16,18 +16,57 @@
package com.vaadin.data.provider;
import java.util.EventObject;
+import java.util.Objects;
/**
* An event fired when the data of a {@code DataProvider} changes.
*
- *
* @see DataProviderListener
*
* @author Vaadin Ltd
* @since 8.0
*
+ *
+ * @param <T>
+ * the data type
*/
-public class DataChangeEvent extends EventObject {
+public class DataChangeEvent<T> extends EventObject {
+
+ /**
+ * An event fired when a single item of a {@code DataProvider} has been
+ * updated.
+ *
+ * @param <T>
+ * the data type
+ */
+ public static class DataRefreshEvent<T> extends DataChangeEvent<T> {
+
+ private final T item;
+
+ /**
+ * Creates a new data refresh event originating from the given data
+ * provider.
+ *
+ * @param source
+ * the data provider, not null
+ * @param item
+ * the updated item, not null
+ */
+ public DataRefreshEvent(DataProvider<T, ?> source, T item) {
+ super(source);
+ Objects.requireNonNull(item, "Refreshed item can't be null");
+ this.item = item;
+ }
+
+ /**
+ * Gets the refreshed item.
+ *
+ * @return the refreshed item
+ */
+ public T getItem() {
+ return item;
+ }
+ }
/**
* Creates a new {@code DataChangeEvent} event originating from the given
@@ -36,13 +75,12 @@ public class DataChangeEvent extends EventObject {
* @param source
* the data provider, not null
*/
- public DataChangeEvent(DataProvider<?, ?> source) {
+ public DataChangeEvent(DataProvider<T, ?> source) {
super(source);
}
@Override
- public DataProvider<?, ?> getSource() {
- return (DataProvider<?, ?>) super.getSource();
+ public DataProvider<T, ?> getSource() {
+ return (DataProvider<T, ?>) super.getSource();
}
-
}
diff --git a/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java b/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java
index 021623555e..9080ad3442 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import com.vaadin.data.provider.DataChangeEvent.DataRefreshEvent;
import com.vaadin.server.AbstractExtension;
import com.vaadin.server.KeyMapper;
import com.vaadin.server.SerializableConsumer;
@@ -465,17 +466,20 @@ public class DataCommunicator<T> extends AbstractExtension {
* @param initialFilter
* the initial filter value to use, or <code>null</code> to not
* use any initial filter value
+ *
+ * @param <F>
+ * the filter type
+ *
* @return a consumer that accepts a new filter value to use
*/
public <F> SerializableConsumer<F> setDataProvider(
DataProvider<T, F> dataProvider, F initialFilter) {
Objects.requireNonNull(dataProvider, "data provider cannot be null");
-
filter = initialFilter;
- this.dataProvider = dataProvider;
-
detachDataProviderListener();
dropAllData();
+ this.dataProvider = dataProvider;
+
/*
* This introduces behavior which influence on the client-server
* communication: now the very first response to the client will always
@@ -556,8 +560,18 @@ public class DataCommunicator<T> extends AbstractExtension {
private void attachDataProviderListener() {
dataProviderUpdateRegistration = getDataProvider()
- .addDataProviderListener(
- event -> getUI().access(() -> reset()));
+ .addDataProviderListener(event -> {
+ getUI().access(() -> {
+ if (event instanceof DataRefreshEvent) {
+ T item = ((DataRefreshEvent<T>) event).getItem();
+ generators.forEach(g -> g.refreshData(item));
+ keyMapper.refresh(item, dataProvider::getId);
+ refresh(item);
+ } else {
+ reset();
+ }
+ });
+ });
}
private void detachDataProviderListener() {
diff --git a/server/src/main/java/com/vaadin/data/provider/DataGenerator.java b/server/src/main/java/com/vaadin/data/provider/DataGenerator.java
index 5e88f7ff66..c5a5a6b9c9 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataGenerator.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataGenerator.java
@@ -62,4 +62,14 @@ public interface DataGenerator<T> extends Serializable {
*/
public default void destroyAllData() {
}
+
+ /**
+ * Informs the {@code DataGenerator} that a data object has been updated.
+ * This method should update any unneeded information stored for given item.
+ *
+ * @param item
+ * the updated item
+ */
+ public default void refreshData(T item) {
+ }
}
diff --git a/server/src/main/java/com/vaadin/data/provider/DataKeyMapper.java b/server/src/main/java/com/vaadin/data/provider/DataKeyMapper.java
index 63bd2d92f8..0ec6748a85 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataKeyMapper.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataKeyMapper.java
@@ -17,6 +17,8 @@ package com.vaadin.data.provider;
import java.io.Serializable;
+import com.vaadin.data.ValueProvider;
+
/**
* DataKeyMapper to map data objects to key strings.
*
@@ -59,4 +61,16 @@ public interface DataKeyMapper<T> extends Serializable {
* Dropped keys are not reused.
*/
void removeAll();
+
+ /**
+ * Updates any existing mappings of given data object. The equality of two
+ * data objects is determined by the equality of their identifiers provided
+ * by the given value provider.
+ *
+ * @param dataObject
+ * the data object to update
+ * @param identifierGetter
+ * the function to get an identifier from a data object
+ */
+ void refresh(T dataObject, ValueProvider<T, Object> identifierGetter);
}
diff --git a/server/src/main/java/com/vaadin/data/provider/DataProvider.java b/server/src/main/java/com/vaadin/data/provider/DataProvider.java
index 380a1f4809..f9c3c80146 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataProvider.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataProvider.java
@@ -88,12 +88,39 @@ public interface DataProvider<T, F> extends Serializable {
Stream<T> fetch(Query<T, F> query);
/**
+ * Refreshes the given item. This method should be used to inform all
+ * {@link DataProviderListener DataProviderListeners} that an item has been
+ * updated or replaced with a new instance.
+ *
+ * @param item
+ * the item to refresh
+ */
+ void refreshItem(T item);
+
+ /**
* Refreshes all data based on currently available data in the underlying
* provider.
*/
void refreshAll();
/**
+ * Gets an identifier for the given item. This identifier is used by the
+ * framework to determine equality between two items.
+ * <p>
+ * Default is to use item itself as its own identifier. If the item has
+ * {@link Object#equals(Object)} and {@link Object#hashCode()} implemented
+ * in a way that it can be compared to other items, no changes are required.
+ *
+ * @param item
+ * the item to get identifier for; not {@code null}
+ * @return the identifier for given item; not {@code null}
+ */
+ public default Object getId(T item) {
+ Objects.requireNonNull(item, "Cannot provide an id for a null item.");
+ return item;
+ }
+
+ /**
* Adds a data provider listener. The listener is called when some piece of
* data is updated.
* <p>
@@ -106,7 +133,7 @@ public interface DataProvider<T, F> extends Serializable {
* the data change listener, not null
* @return a registration for the listener
*/
- Registration addDataProviderListener(DataProviderListener listener);
+ Registration addDataProviderListener(DataProviderListener<T> listener);
/**
* Wraps this data provider to create a data provider that uses a different
diff --git a/server/src/main/java/com/vaadin/data/provider/DataProviderListener.java b/server/src/main/java/com/vaadin/data/provider/DataProviderListener.java
index 582bdc1d86..da97e34c80 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataProviderListener.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataProviderListener.java
@@ -23,9 +23,12 @@ import java.io.Serializable;
*
* @author Vaadin Ltd
* @since 8.0
+ *
+ * @param <T>
+ * the data type
*/
@FunctionalInterface
-public interface DataProviderListener extends Serializable {
+public interface DataProviderListener<T> extends Serializable {
/**
* Invoked when this listener receives a data change event from a data
@@ -39,5 +42,5 @@ public interface DataProviderListener extends Serializable {
* @param event
* the received event, not null
*/
- void onDataChange(DataChangeEvent event);
+ void onDataChange(DataChangeEvent<T> event);
}
diff --git a/server/src/main/java/com/vaadin/data/provider/DataProviderWrapper.java b/server/src/main/java/com/vaadin/data/provider/DataProviderWrapper.java
index 1eabb67abe..5195aa7837 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataProviderWrapper.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataProviderWrapper.java
@@ -65,7 +65,18 @@ public abstract class DataProviderWrapper<T, F, M>
}
@Override
- public Registration addDataProviderListener(DataProviderListener listener) {
+ public void refreshItem(T item) {
+ dataProvider.refreshItem(item);
+ }
+
+ @Override
+ public Object getId(T item) {
+ return dataProvider.getId(item);
+ }
+
+ @Override
+ public Registration addDataProviderListener(
+ DataProviderListener<T> listener) {
return dataProvider.addDataProviderListener(listener);
}
diff --git a/server/src/main/java/com/vaadin/server/KeyMapper.java b/server/src/main/java/com/vaadin/server/KeyMapper.java
index 471fea3e69..7ed723be66 100644
--- a/server/src/main/java/com/vaadin/server/KeyMapper.java
+++ b/server/src/main/java/com/vaadin/server/KeyMapper.java
@@ -19,6 +19,7 @@ package com.vaadin.server;
import java.io.Serializable;
import java.util.HashMap;
+import com.vaadin.data.ValueProvider;
import com.vaadin.data.provider.DataKeyMapper;
/**
@@ -113,4 +114,17 @@ public class KeyMapper<V> implements DataKeyMapper<V>, Serializable {
public boolean containsKey(String key) {
return keyObjectMap.containsKey(key);
}
+
+ @Override
+ public void refresh(V dataObject,
+ ValueProvider<V, Object> identifierGetter) {
+ Object id = identifierGetter.apply(dataObject);
+ objectKeyMap.entrySet().stream()
+ .filter(e -> identifierGetter.apply(e.getKey()).equals(id))
+ .findAny().ifPresent(e -> {
+ String key = objectKeyMap.remove(e.getKey());
+ objectKeyMap.put(dataObject, key);
+ keyObjectMap.put(key, dataObject);
+ });
+ }
}
diff --git a/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java b/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
index 22df69da5c..9947067288 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.ui;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -31,6 +32,7 @@ import com.vaadin.data.HasValue;
import com.vaadin.data.SelectionModel;
import com.vaadin.data.SelectionModel.Multi;
import com.vaadin.data.provider.DataGenerator;
+import com.vaadin.data.provider.DataProvider;
import com.vaadin.event.selection.MultiSelectionEvent;
import com.vaadin.event.selection.MultiSelectionListener;
import com.vaadin.server.Resource;
@@ -59,7 +61,7 @@ import elemental.json.JsonObject;
public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
implements MultiSelect<T> {
- private Set<T> selection = new LinkedHashSet<>();
+ private List<T> selection = new ArrayList<>();
private class MultiSelectServerRpcImpl implements MultiSelectServerRpc {
@Override
@@ -122,6 +124,11 @@ public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
public void destroyAllData() {
AbstractMultiSelect.this.deselectAll();
}
+
+ @Override
+ public void refreshData(T item) {
+ refreshSelectedItem(item);
+ }
}
/**
@@ -228,9 +235,9 @@ public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
@Override
public Registration addValueChangeListener(
HasValue.ValueChangeListener<Set<T>> listener) {
- return addSelectionListener(event -> listener.valueChange(
- new ValueChangeEvent<>(this, event.getOldValue(),
- event.isUserOriginated())));
+ return addSelectionListener(
+ event -> listener.valueChange(new ValueChangeEvent<>(this,
+ event.getOldValue(), event.isUserOriginated())));
}
/**
@@ -346,12 +353,15 @@ public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
return;
}
- updateSelection(Set::clear, false);
+ updateSelection(Collection::clear, false);
}
@Override
public boolean isSelected(T item) {
- return selection.contains(item);
+ DataProvider<T, ?> dataProvider = internalGetDataProvider();
+ Object id = dataProvider.getId(item);
+ return selection.stream().map(dataProvider::getId).anyMatch(id::equals);
+
}
/**
@@ -469,7 +479,7 @@ public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
return item;
}
- private void updateSelection(SerializableConsumer<Set<T>> handler,
+ private void updateSelection(SerializableConsumer<Collection<T>> handler,
boolean userOriginated) {
LinkedHashSet<T> oldSelection = new LinkedHashSet<>(selection);
handler.accept(selection);
@@ -479,4 +489,15 @@ public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
getDataCommunicator().reset();
}
+
+ private final void refreshSelectedItem(T item) {
+ DataProvider<T, ?> dataProvider = internalGetDataProvider();
+ Object id = dataProvider.getId(item);
+ for (int i = 0; i < selection.size(); ++i) {
+ if (id.equals(dataProvider.getId(selection.get(i)))) {
+ selection.set(i, item);
+ return;
+ }
+ }
+ }
}
diff --git a/server/src/main/java/com/vaadin/ui/components/grid/MultiSelectionModelImpl.java b/server/src/main/java/com/vaadin/ui/components/grid/MultiSelectionModelImpl.java
index 551918ef85..97f79a4655 100644
--- a/server/src/main/java/com/vaadin/ui/components/grid/MultiSelectionModelImpl.java
+++ b/server/src/main/java/com/vaadin/ui/components/grid/MultiSelectionModelImpl.java
@@ -15,9 +15,12 @@
*/
package com.vaadin.ui.components.grid;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
@@ -119,7 +122,7 @@ public class MultiSelectionModelImpl<T> extends AbstractSelectionModel<T>
}
}
- private Set<T> selection = new LinkedHashSet<>();
+ private List<T> selection = new ArrayList<>();
private SelectAllCheckBoxVisibility selectAllCheckBoxVisibility = SelectAllCheckBoxVisibility.DEFAULT;
@@ -199,8 +202,20 @@ public class MultiSelectionModelImpl<T> extends AbstractSelectionModel<T>
@Override
public boolean isSelected(T item) {
return isAllSelected()
- || com.vaadin.ui.components.grid.MultiSelectionModel.super.isSelected(
- item);
+ || selectionContainsId(getGrid().getDataProvider().getId(item));
+ }
+
+ /**
+ * Returns if the given id belongs to one of the selected items.
+ *
+ * @param id
+ * the id to check for
+ * @return {@code true} if id is selected, {@code false} if not
+ */
+ protected boolean selectionContainsId(Object id) {
+ DataProvider<T, ?> dataProvider = getGrid().getDataProvider();
+ return selection.stream().map(dataProvider::getId)
+ .anyMatch(i -> id.equals(i));
}
@Override
@@ -447,7 +462,7 @@ public class MultiSelectionModelImpl<T> extends AbstractSelectionModel<T>
return getState(false).selectionAllowed;
}
- private void doUpdateSelection(Consumer<Set<T>> handler,
+ private void doUpdateSelection(Consumer<Collection<T>> handler,
boolean userOriginated) {
if (getParent() == null) {
throw new IllegalStateException(
@@ -460,4 +475,16 @@ public class MultiSelectionModelImpl<T> extends AbstractSelectionModel<T>
fireEvent(new MultiSelectionEvent<>(getGrid(), asMultiSelect(),
oldSelection, userOriginated));
}
+
+ @Override
+ public void refreshData(T item) {
+ DataProvider<T, ?> dataProvider = getGrid().getDataProvider();
+ Object refreshId = dataProvider.getId(item);
+ for (int i = 0; i < selection.size(); ++i) {
+ if (dataProvider.getId(selection.get(i)).equals(refreshId)) {
+ selection.set(i, item);
+ return;
+ }
+ }
+ }
}
diff --git a/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java b/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java
index 42ca337e65..cd985f473a 100644
--- a/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java
+++ b/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java
@@ -284,4 +284,18 @@ public class SingleSelectionModelImpl<T> extends AbstractSelectionModel<T>
}
};
}
+
+ @Override
+ public void refreshData(T item) {
+ if (isSelected(item)) {
+ selectedItem = item;
+ }
+ }
+
+ @Override
+ public boolean isSelected(T item) {
+ return item != null && selectedItem != null
+ && getGrid().getDataProvider().getId(selectedItem)
+ .equals(getGrid().getDataProvider().getId(item));
+ }
}