diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2016-07-08 18:30:47 +0300 |
---|---|---|
committer | Ilia Motornyi <elmot@vaadin.com> | 2016-07-12 10:41:56 +0000 |
commit | ba228972ae734f3f596edb7a2382b0df19a1db9c (patch) | |
tree | 99f7e0dbb19ec75e6a8fd4a18a37bccb3829b9fa | |
parent | 4f6cdc327b6cfc40d288acd1052c1cf705cce3eb (diff) | |
download | vaadin-framework-ba228972ae734f3f596edb7a2382b0df19a1db9c.tar.gz vaadin-framework-ba228972ae734f3f596edb7a2382b0df19a1db9c.zip |
Simplify DataSource to be a function that provides Stream of values
This patch also removes the old automatic update logic.
Change-Id: Idb50137eee2592c1acd14ff67f577ad5edbbd2ff
-rw-r--r-- | server/src/main/java/com/vaadin/tokka/server/communication/data/AbstractDataSource.java | 97 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/tokka/server/communication/data/DataCommunicator.java | 91 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/tokka/server/communication/data/DataSource.java | 69 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/tokka/server/communication/data/InMemoryDataSource.java (renamed from server/src/main/java/com/vaadin/tokka/server/communication/data/ListDataSource.java) | 38 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/tokka/data/datasource/InMemoryDataSourceTest.java | 55 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/tokka/data/datasource/ListDataSourceTest.java | 100 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/tokka/ui/components/AbstractListingTest.java | 25 | ||||
-rw-r--r-- | uitest/src/main/java/com/vaadin/tokka/tests/components/ListingTestUI.java | 5 |
8 files changed, 92 insertions, 388 deletions
diff --git a/server/src/main/java/com/vaadin/tokka/server/communication/data/AbstractDataSource.java b/server/src/main/java/com/vaadin/tokka/server/communication/data/AbstractDataSource.java deleted file mode 100644 index 4e2bfbf6bf..0000000000 --- a/server/src/main/java/com/vaadin/tokka/server/communication/data/AbstractDataSource.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.tokka.server.communication.data; - -import java.util.LinkedHashSet; -import java.util.Set; - -import com.vaadin.tokka.event.Registration; - -/** - * Base class for AbstractDataSource. Provides tracking for - * {@link DataChangeHandler}s and helper methods to call them. - * - * @since - */ -public abstract class AbstractDataSource<T> implements DataSource<T> { - - protected final Set<DataChangeHandler<T>> handlers = new LinkedHashSet<DataChangeHandler<T>>(); - - @Override - public Registration addDataChangeHandler(DataChangeHandler<T> handler) { - if (handler != null) { - handlers.add(handler); - return () -> handlers.remove(handler); - } - return () -> { /* NO-OP */ }; - } - - /** - * Informs all handlers of a generic change in the data. This usually - * triggers a full cache invalidation and refresh of all data, which is - * usually an expensive operation. Should be called when none of the other - * methods help. - * - * @see #fireDataAppend(Object) - * @see #fireDataRemove(Object) - * @see #fireDataUpdate(Object) - */ - protected void fireDataChange() { - for (DataChangeHandler<T> handler : handlers) { - handler.onDataChange(); - } - } - - /** - * Informs all handlers of an added data object in the back end. This method - * should only be called when the newly added data object is the last object - * in the back end. Other additions can be handled with - * {@link #fireDataChange()}. - * - * @param data - * added data object - */ - protected void fireDataAppend(T data) { - for (DataChangeHandler<T> handler : handlers) { - handler.onDataAppend(data); - } - } - - /** - * Informs all handlers of a data object that was removed from the back end. - * - * @param data - * removed data object - */ - protected void fireDataRemove(T data) { - for (DataChangeHandler<T> handler : handlers) { - handler.onDataRemove(data); - } - } - - /** - * Informs all handlers of an existing data object that was updated in the - * back end. - * - * @param data - * updated data object - */ - protected void fireDataUpdate(T data) { - for (DataChangeHandler<T> handler : handlers) { - handler.onDataUpdate(data); - } - } -} diff --git a/server/src/main/java/com/vaadin/tokka/server/communication/data/DataCommunicator.java b/server/src/main/java/com/vaadin/tokka/server/communication/data/DataCommunicator.java index 19b4ed8965..0a9e3f34c7 100644 --- a/server/src/main/java/com/vaadin/tokka/server/communication/data/DataCommunicator.java +++ b/server/src/main/java/com/vaadin/tokka/server/communication/data/DataCommunicator.java @@ -25,7 +25,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import com.vaadin.server.AbstractExtension; -import com.vaadin.server.ClientConnector; import com.vaadin.shared.data.DataRequestRpc; import com.vaadin.shared.data.typed.DataCommunicatorClientRpc; import com.vaadin.shared.data.typed.DataProviderConstants; @@ -72,8 +71,8 @@ public class DataCommunicator<T> extends AbstractExtension { * longer needed. Data tracking is based on key string provided by * {@link DataKeyMapper}. * <p> - * When the {@link DataCommunicator} is pushing new data to the client-side via - * {@link DataCommunicator#pushData(long, Collection)}, + * When the {@link DataCommunicator} is pushing new data to the client-side + * via {@link DataCommunicator#pushData(long, Collection)}, * {@link #addActiveData(Collection)} and {@link #cleanUp(Collection)} are * called with the same parameter. In the clean up method any dropped data * objects that are not in the given collection will be cleaned up and @@ -173,8 +172,6 @@ public class DataCommunicator<T> extends AbstractExtension { protected DataCommunicatorClientRpc rpc; protected DataSource<T> dataSource; - private Registration dataChangeHandler; - private DetachListener detachListener; private DataKeyMapper<T> keyMapper; private boolean reset = false; @@ -186,8 +183,6 @@ public class DataCommunicator<T> extends AbstractExtension { this.dataSource = dataSource; rpc = getRpcProxy(DataCommunicatorClientRpc.class); registerRpc(createRpc()); - dataChangeHandler = this.dataSource - .addDataChangeHandler(createDataChangeHandler()); keyMapper = createKeyMapper(); } @@ -200,11 +195,13 @@ public class DataCommunicator<T> extends AbstractExtension { super.beforeClientResponse(initial); if (initial || reset) { - rpc.reset(dataSource.size()); + // FIXME: Rethink the size question. + rpc.reset((int) dataSource.apply(null).count()); } if (!pushRows.isEmpty()) { - Stream<T> rowsToPush = dataSource.request() + // FIXME: Query object + Stream<T> rowsToPush = dataSource.apply(null) .skip(pushRows.getStart()).limit(pushRows.length()); pushData(pushRows.getStart(), rowsToPush); } @@ -223,32 +220,6 @@ public class DataCommunicator<T> extends AbstractExtension { updatedData.clear(); } - @Override - public void attach() { - super.attach(); - - if (detachListener == null) { - detachListener = new DetachListener() { - - @Override - public void detach(DetachEvent event) { - cleanUp(); - } - }; - getUI().addDetachListener(detachListener); - } - } - - @Override - public void setParent(ClientConnector parent) { - if (getParent() != null && parent == null) { - // Removing from parent, clean up. - cleanUp(); - } - - super.setParent(parent); - } - /** * Adds a {@link TypedDataGenerator} to this {@link DataCommunicator}. * @@ -341,22 +312,6 @@ public class DataCommunicator<T> extends AbstractExtension { } /** - * Clean up method for removing all listeners attached by the - * {@link DataCommunicator}. This method is called from {@link #remove()} or - * when the UI gets detached. - */ - protected void cleanUp() { - if (dataSource != null) { - dataChangeHandler.removeHandler(); - dataChangeHandler = null; - } - if (detachListener != null) { - getUI().removeDetachListener(detachListener); - detachListener = null; - } - } - - /** * Informs the DataProvider that a data object has been added. It is assumed * to be the last object in the collection. * @@ -406,7 +361,7 @@ public class DataCommunicator<T> extends AbstractExtension { } /** - * Creates a {@link DataKeyMapper} to use with this {@link DataCommunicator}. + * Creates a {@link DataKeyMapper} to use with this DataCommunicator. * <p> * This method is called from the constructor. * @@ -426,36 +381,4 @@ public class DataCommunicator<T> extends AbstractExtension { protected DataRequestRpc createRpc() { return new SimpleDataRequestRpc(); } - - /** - * Creates a {@link DataChangeHandler} to use with the {@link DataSource}. - * <p> - * This method is called from the constructor. - * - * @return data change handler - */ - protected DataChangeHandler<T> createDataChangeHandler() { - return new DataChangeHandler<T>() { - - @Override - public void onDataChange() { - reset(); - } - - @Override - public void onDataAppend(T data) { - add(data); - } - - @Override - public void onDataRemove(T data) { - remove(data); - } - - @Override - public void onDataUpdate(T data) { - refresh(data); - } - }; - } }
\ No newline at end of file diff --git a/server/src/main/java/com/vaadin/tokka/server/communication/data/DataSource.java b/server/src/main/java/com/vaadin/tokka/server/communication/data/DataSource.java index ea851a04f7..01257bf755 100644 --- a/server/src/main/java/com/vaadin/tokka/server/communication/data/DataSource.java +++ b/server/src/main/java/com/vaadin/tokka/server/communication/data/DataSource.java @@ -18,6 +18,7 @@ package com.vaadin.tokka.server.communication.data; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; +import java.util.function.Function; import java.util.stream.Stream; import com.vaadin.tokka.event.Registration; @@ -25,74 +26,40 @@ import com.vaadin.tokka.event.Registration; /** * Minimal DataSource API for communication between the DataProvider and a back * end service. + * <p> + * FIXME: Missing Query class * * @since * @param <T> * data type */ -public interface DataSource<T> extends Serializable { +public interface DataSource<T> extends Function<Object, Stream<T>>, + Serializable { /** - * Requests data from the back end. - * - * @return stream of results - */ - Stream<T> request(/* Query query */); - - /** - * Saves a data object to the back end. If it's a new object, it should be - * created in the back end. Existing objects with changes should be stored. - * - * @param data - * data object to save - */ - void save(T data); - - /** - * Removes the given data object from the back end. - * - * @param data - * data object to remove - */ - void remove(T data); - - /** - * TODO: Decide the fate of the size method. - * - * @return size of the data source - */ - int size(); - - /** - * Adds a new DataChangeHandler to this DataSource. DataChangeHandler is - * called when changes occur in DataSource. - * - * @param handler - * data change handler - */ - Registration addDataChangeHandler(DataChangeHandler<T> handler); - - /** - * This method creates a new {@link ListDataSource} from a given Collection. - * The ListDataSource creates a protective List copy of all the contents in - * the Collection. + * This method creates a new {@link InMemoryDataSource} from a given + * Collection. The InMemoryDataSource creates a protective List copy of all + * the contents in the Collection. * * @param data * collection of data - * @return list data source + * @return in-memory data source */ - public static <T> ListDataSource<T> create(Collection<T> data) { - return new ListDataSource<>(data); + public static <T> InMemoryDataSource<T> create(Collection<T> data) { + return new InMemoryDataSource<>(data); } /** - * This method creates a new {@link ListDataSource} from given objects. + * This method creates a new {@link InMemoryDataSource} from given + * objects.The InMemoryDataSource creates a protective List copy of all the + * contents in the array. * * @param data * data objects - * @return list data source + * @return in-memory data source */ - public static <T> ListDataSource<T> create(T... data) { - return new ListDataSource<>(Arrays.asList(data)); + @SafeVarargs + public static <T> InMemoryDataSource<T> create(T... data) { + return new InMemoryDataSource<>(Arrays.asList(data)); } }
\ No newline at end of file diff --git a/server/src/main/java/com/vaadin/tokka/server/communication/data/ListDataSource.java b/server/src/main/java/com/vaadin/tokka/server/communication/data/InMemoryDataSource.java index ab9f84940b..5f743e2ca1 100644 --- a/server/src/main/java/com/vaadin/tokka/server/communication/data/ListDataSource.java +++ b/server/src/main/java/com/vaadin/tokka/server/communication/data/InMemoryDataSource.java @@ -18,6 +18,7 @@ package com.vaadin.tokka.server.communication.data; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.Function; import java.util.stream.Stream; /** @@ -26,9 +27,10 @@ import java.util.stream.Stream; * @param <T> * data type */ -public class ListDataSource<T> extends AbstractDataSource<T> { +public class InMemoryDataSource<T> implements DataSource<T> { - private List<T> backend; + // FIXME: Missing Query object + private Function<Object, Stream<T>> request; /** * Constructs a new ListDataSource. This method makes a protective copy of @@ -37,35 +39,13 @@ public class ListDataSource<T> extends AbstractDataSource<T> { * @param collection * initial data */ - public ListDataSource(Collection<T> collection) { - backend = new ArrayList<T>(collection); + public InMemoryDataSource(Collection<T> collection) { + final List<T> backend = new ArrayList<T>(collection); + request = query -> backend.stream(); } @Override - public void save(T data) { - if (!backend.contains(data)) { - backend.add(data); - fireDataAppend(data); - } else { - fireDataUpdate(data); - } - } - - @Override - public void remove(T data) { - if (backend.contains(data)) { - backend.remove(data); - fireDataRemove(data); - } - } - - @Override - public Stream<T> request() { - return backend.stream(); - } - - @Override - public int size() { - return backend.size(); + public Stream<T> apply(Object query) { + return request.apply(query); } } diff --git a/server/src/test/java/com/vaadin/tokka/data/datasource/InMemoryDataSourceTest.java b/server/src/test/java/com/vaadin/tokka/data/datasource/InMemoryDataSourceTest.java new file mode 100644 index 0000000000..092f70b395 --- /dev/null +++ b/server/src/test/java/com/vaadin/tokka/data/datasource/InMemoryDataSourceTest.java @@ -0,0 +1,55 @@ +package com.vaadin.tokka.data.datasource; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.tokka.server.communication.data.DataSource; +import com.vaadin.tokka.server.communication.data.InMemoryDataSource; + +public class InMemoryDataSourceTest { + + private static class StrBean { + + private String value; + + public StrBean(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + } + + private InMemoryDataSource<StrBean> dataSource; + private List<StrBean> data; + + @Before + public void setUp() { + data = createData(); + dataSource = DataSource.create(data); + } + + @Test + public void testListContainsAllData() { + dataSource.apply(null).forEach(str -> assertTrue(data.contains(str))); + } + + private List<StrBean> createData() { + List<StrBean> list = new ArrayList<>(); + Stream.of("Foo", "Bar", "Baz").map(StrBean::new).forEach(list::add); + return list; + } + +} diff --git a/server/src/test/java/com/vaadin/tokka/data/datasource/ListDataSourceTest.java b/server/src/test/java/com/vaadin/tokka/data/datasource/ListDataSourceTest.java deleted file mode 100644 index 58a3fa8b48..0000000000 --- a/server/src/test/java/com/vaadin/tokka/data/datasource/ListDataSourceTest.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.vaadin.tokka.data.datasource; - -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import org.easymock.EasyMock; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.tokka.server.communication.data.DataChangeHandler; -import com.vaadin.tokka.server.communication.data.DataSource; -import com.vaadin.tokka.server.communication.data.ListDataSource; - -public class ListDataSourceTest { - - private static class StrBean { - - private String value; - - public StrBean(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - private ListDataSource<StrBean> dataSource; - private List<StrBean> data; - private DataChangeHandler<StrBean> handler; - - @Before - public void setUp() { - data = createData(); - dataSource = DataSource.create(data); - handler = EasyMock.mock(DataChangeHandler.class); - } - - @Test - public void testListContainsAllData() { - EasyMock.replay(handler); - dataSource.request().forEach(str -> assertTrue(data.contains(str))); - } - - @Test - public void testListFiresDataAddEvent() { - StrBean strBean = new StrBean("Spam"); - handler.onDataAppend(strBean); - EasyMock.expectLastCall().times(1); - EasyMock.replay(handler); - - dataSource.addDataChangeHandler(handler); - dataSource.save(strBean); - } - - @Test - public void testListFiresDataRemoveEvent() { - StrBean strBean = data.get(0); - handler.onDataRemove(strBean); - EasyMock.expectLastCall().times(1); - EasyMock.replay(handler); - - dataSource.addDataChangeHandler(handler); - dataSource.remove(strBean); - } - - @Test - public void testListFiresDataUpdateEvent() { - StrBean strBean = data.get(0); - handler.onDataUpdate(strBean); - EasyMock.expectLastCall().times(1); - EasyMock.replay(handler); - - dataSource.addDataChangeHandler(handler); - strBean.setValue("Fuu"); - dataSource.save(strBean); - } - - @After - public void tearDown() { - EasyMock.verify(handler); - } - - private List<StrBean> createData() { - List<StrBean> list = new ArrayList<>(); - Stream.of("Foo", "Bar", "Baz").map(StrBean::new).forEach(list::add); - return list; - } - -} diff --git a/server/src/test/java/com/vaadin/tokka/ui/components/AbstractListingTest.java b/server/src/test/java/com/vaadin/tokka/ui/components/AbstractListingTest.java index 614e1aba72..242b5519df 100644 --- a/server/src/test/java/com/vaadin/tokka/ui/components/AbstractListingTest.java +++ b/server/src/test/java/com/vaadin/tokka/ui/components/AbstractListingTest.java @@ -2,15 +2,11 @@ package com.vaadin.tokka.ui.components; import static org.junit.Assert.assertEquals; -import java.util.stream.Stream; - import org.junit.Before; import org.junit.Test; -import com.vaadin.tokka.server.communication.data.AbstractDataSource; import com.vaadin.tokka.server.communication.data.DataCommunicator; import com.vaadin.tokka.server.communication.data.DataSource; -import com.vaadin.tokka.ui.components.AbstractListing; import com.vaadin.tokka.ui.components.AbstractListing.AbstractListingExtension; import elemental.json.JsonObject; @@ -49,26 +45,7 @@ public class AbstractListingTest { @Before public void setUp() { - testComponent.setDataSource(new AbstractDataSource<String>() { - - @Override - public void save(String data) { - } - - @Override - public void remove(String data) { - } - - @Override - public Stream<String> request() { - return Stream.of("Foo"); - } - - @Override - public int size() { - return 1; - } - }); + testComponent.setDataSource(DataSource.create("Foo")); } @Test diff --git a/uitest/src/main/java/com/vaadin/tokka/tests/components/ListingTestUI.java b/uitest/src/main/java/com/vaadin/tokka/tests/components/ListingTestUI.java index 683be11e47..a66ab31fda 100644 --- a/uitest/src/main/java/com/vaadin/tokka/tests/components/ListingTestUI.java +++ b/uitest/src/main/java/com/vaadin/tokka/tests/components/ListingTestUI.java @@ -62,7 +62,6 @@ public class ListingTestUI extends AbstractTestUI { .nextInt(100))); } return beans; - } } @@ -82,8 +81,8 @@ public class ListingTestUI extends AbstractTestUI { .forEach(s -> Notification.show(s)))); hLayout.addComponent(new Button("Random select", e -> { DataSource<String> ds = select.getDataSource(); - int skip = r.nextInt(ds.size()); - ds.request().skip(skip).findFirst() + int skip = r.nextInt((int) ds.apply(null).count()); + ds.apply(null).skip(skip).findFirst() .ifPresent(select.getSelectionModel()::select); })); |