Skip to content

Commit cdfde35

Browse files
authored
feat: support DataProviderWrapper better in AbstractDataView (#18317)
* feat: support DataProviderWrapper better in AbstractDataView Adds in `AbstractDataView` a better support for wrapper data providers that implements `DataProviderWrapper`. `AbstractDataView` won't throw exception anymore if wrapped data container is supported by the data view implementation. Adds public `getWrappedDataProvider` method in `DataProviderWrapper`. Related-to: #18088 * chore: changed getWrappedDataProvider to package-private
1 parent 64b220e commit cdfde35

File tree

5 files changed

+176
-3
lines changed

5 files changed

+176
-3
lines changed

flow-data/src/main/java/com/vaadin/flow/data/provider/AbstractDataView.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public AbstractDataView(
7171
* the data provider.
7272
*/
7373
if (isDataProviderInitialized(dataProviderType)) {
74-
verifyDataProviderType(dataProviderType);
74+
verifyDataProviderType(dataProviderSupplier.get());
7575
}
7676
}
7777

@@ -115,6 +115,32 @@ protected final void verifyDataProviderType(Class<?> dataProviderType) {
115115
}
116116
}
117117

118+
/**
119+
* Verifies an obtained {@link DataProvider} type is appropriate for current
120+
* Data View type. If the data provider is a wrapper, then the wrapped data
121+
* provider is verified too.
122+
*
123+
* @param dataProvider
124+
* data provider to be verified
125+
* @throws IllegalStateException
126+
* if data provider type is incompatible with data view type
127+
*/
128+
protected final void verifyDataProviderType(
129+
DataProvider<T, ?> dataProvider) {
130+
try {
131+
verifyDataProviderType(dataProvider.getClass());
132+
} catch (IllegalStateException e) {
133+
if (DataProviderWrapper.class
134+
.isAssignableFrom(dataProvider.getClass())) {
135+
verifyDataProviderType(
136+
((DataProviderWrapper<T, ?, ?>) dataProvider)
137+
.getWrappedDataProvider());
138+
} else {
139+
throw e;
140+
}
141+
}
142+
}
143+
118144
@Override
119145
public Stream<T> getItems() {
120146
return dataProviderSupplier.get().fetch(new Query<>());

flow-data/src/main/java/com/vaadin/flow/data/provider/AbstractLazyDataView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public AbstractLazyDataView(DataCommunicator<T> dataCommunicator,
5555
* @return the data communicator
5656
*/
5757
protected DataCommunicator<T> getDataCommunicator() {
58-
verifyDataProviderType(dataCommunicator.getDataProvider().getClass());
58+
verifyDataProviderType(dataCommunicator.getDataProvider());
5959
return dataCommunicator;
6060
}
6161

flow-data/src/main/java/com/vaadin/flow/data/provider/AbstractListDataView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ protected Class<?> getSupportedDataProviderType() {
203203
protected ListDataProvider<T> getDataProvider() {
204204
final DataProvider<T, ?> dataProvider = dataProviderSupplier.get();
205205
Objects.requireNonNull(dataProvider, "DataProvider cannot be null");
206-
verifyDataProviderType(dataProvider.getClass());
206+
verifyDataProviderType(dataProvider);
207207
return (ListDataProvider<T>) dataProvider;
208208
}
209209

flow-data/src/main/java/com/vaadin/flow/data/provider/DataProviderWrapper.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ protected DataProviderWrapper(DataProvider<T, M> dataProvider) {
5454
"The wrapped data provider cannot be null.");
5555
}
5656

57+
/**
58+
* Gets wrapped data provider.
59+
*
60+
* @return the wrapped data provider
61+
*/
62+
DataProvider<T, M> getWrappedDataProvider() {
63+
return dataProvider;
64+
}
65+
5766
@Override
5867
public boolean isInMemory() {
5968
return dataProvider.isInMemory();

flow-data/src/test/java/com/vaadin/flow/data/provider/AbstractDataViewTest.java

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
import java.util.ArrayList;
2020
import java.util.Arrays;
2121
import java.util.Collection;
22+
import java.util.List;
2223
import java.util.concurrent.atomic.AtomicInteger;
2324
import java.util.concurrent.atomic.AtomicReference;
2425
import java.util.stream.Stream;
2526

2627
import com.vaadin.flow.component.Component;
2728
import com.vaadin.flow.component.ComponentUtil;
2829
import com.vaadin.flow.component.Tag;
30+
import com.vaadin.flow.function.SerializablePredicate;
2931
import com.vaadin.flow.function.SerializableSupplier;
32+
import com.vaadin.flow.shared.Registration;
3033
import com.vaadin.flow.tests.data.bean.Item;
3134
import org.junit.Assert;
3235
import org.junit.Before;
@@ -38,6 +41,8 @@ public class AbstractDataViewTest {
3841

3942
private ListDataProvider<Item> dataProvider;
4043

44+
private DataProvider<Item, ?> wrapperDataProvider;
45+
4146
private AbstractDataView<Item> dataView;
4247

4348
private Component component;
@@ -100,6 +105,139 @@ public void refreshAll_listenersNotified() {
100105
Assert.assertEquals(dataProvider, refreshAllEvent.get().getSource());
101106
}
102107

108+
@Test
109+
public void verifyDataProviderType_wrappedDataProviderIsSupported() {
110+
// starting with EmptyDataProvider to bypass checking too early in
111+
// the DataViewImpl constructor.
112+
wrapperDataProvider = new DataCommunicator.EmptyDataProvider<>();
113+
DataViewImpl dataView = new DataViewImpl(() -> wrapperDataProvider,
114+
component) {
115+
@Override
116+
public Class<?> getSupportedDataProviderType() {
117+
return InMemoryDataProvider.class;
118+
}
119+
};
120+
wrapperDataProvider = getWrapperDataProvider();
121+
dataView.verifyDataProviderType(wrapperDataProvider);
122+
}
123+
124+
@Test
125+
public void verifyDataProviderType_withConfigurableFilter_wrappedDataProviderIsSupported() {
126+
wrapperDataProvider = new DataCommunicator.EmptyDataProvider<>();
127+
DataViewImpl dataView = new DataViewImpl(() -> wrapperDataProvider,
128+
component) {
129+
@Override
130+
public Class<?> getSupportedDataProviderType() {
131+
return InMemoryDataProvider.class;
132+
}
133+
};
134+
wrapperDataProvider = dataProvider.withConfigurableFilter();
135+
dataView.verifyDataProviderType(wrapperDataProvider);
136+
}
137+
138+
@Test
139+
public void verifyDataProviderType_wrappedDataProviderIsNotSupported() {
140+
wrapperDataProvider = new DataCommunicator.EmptyDataProvider<>();
141+
DataViewImpl dataView = new DataViewImpl(() -> wrapperDataProvider,
142+
component) {
143+
@Override
144+
public Class<?> getSupportedDataProviderType() {
145+
return BackEndDataProvider.class;
146+
}
147+
};
148+
wrapperDataProvider = getWrapperDataProvider();
149+
Assert.assertThrows(IllegalStateException.class,
150+
() -> dataView.verifyDataProviderType(wrapperDataProvider));
151+
}
152+
153+
@Test
154+
public void verifyDataProviderType_withConfigurableFilter_wrappedDataProviderIsNotSupported() {
155+
wrapperDataProvider = new DataCommunicator.EmptyDataProvider<>();
156+
DataViewImpl dataView = new DataViewImpl(() -> wrapperDataProvider,
157+
component) {
158+
@Override
159+
public Class<?> getSupportedDataProviderType() {
160+
return BackEndDataProvider.class;
161+
}
162+
};
163+
wrapperDataProvider = dataProvider.withConfigurableFilter();
164+
Assert.assertThrows(IllegalStateException.class,
165+
() -> dataView.verifyDataProviderType(wrapperDataProvider));
166+
}
167+
168+
@Test
169+
public void verifyDataProviderType_wrapperIsBackEndDataProvider_wrapperDataProviderIsSupported() {
170+
wrapperDataProvider = new DataCommunicator.EmptyDataProvider<>();
171+
DataViewImpl dataView = new DataViewImpl(() -> wrapperDataProvider,
172+
component) {
173+
@Override
174+
public Class<?> getSupportedDataProviderType() {
175+
return BackEndDataProvider.class;
176+
}
177+
};
178+
wrapperDataProvider = new BackEndDataProviderWrapper(dataProvider);
179+
dataView.verifyDataProviderType(wrapperDataProvider);
180+
}
181+
182+
private DataProvider<Item, Object> getWrapperDataProvider() {
183+
return new DataProviderWrapper<Item, Object, SerializablePredicate<Item>>(
184+
dataProvider) {
185+
@Override
186+
protected SerializablePredicate<Item> getFilter(Query query) {
187+
return null;
188+
}
189+
190+
@Override
191+
public Stream fetch(Query query) {
192+
return null;
193+
}
194+
};
195+
}
196+
197+
// BackEndDataProvider that is also a DataProviderWrapper
198+
private static class BackEndDataProviderWrapper extends
199+
DataProviderWrapper<Item, Object, SerializablePredicate<Item>>
200+
implements BackEndDataProvider<Item, Object> {
201+
protected BackEndDataProviderWrapper(
202+
DataProvider<Item, SerializablePredicate<Item>> dataProvider) {
203+
super(dataProvider);
204+
}
205+
206+
@Override
207+
public Stream fetch(Query query) {
208+
return null;
209+
}
210+
211+
@Override
212+
public void setSortOrders(List<QuerySortOrder> sortOrders) {
213+
}
214+
215+
@Override
216+
public int size(Query<Item, Object> query) {
217+
return 0;
218+
}
219+
220+
@Override
221+
protected SerializablePredicate<Item> getFilter(
222+
Query<Item, Object> query) {
223+
return null;
224+
}
225+
226+
@Override
227+
public void refreshItem(Item item) {
228+
}
229+
230+
@Override
231+
public void refreshAll() {
232+
}
233+
234+
@Override
235+
public Registration addDataProviderListener(
236+
DataProviderListener<Item> listener) {
237+
return null;
238+
}
239+
}
240+
103241
/**
104242
* setIdentifierProvider is tested in AbstractListDataView since it has the
105243
* container(T item) method.

0 commit comments

Comments
 (0)