Change-Id: Ic1fded7f26e3f63c234c6e5bebf8f8fed22e6365feature/vaadin8-book
@@ -171,14 +171,14 @@ public class DataCommunicator<T> extends AbstractExtension { | |||
protected ActiveDataHandler handler = new ActiveDataHandler(); | |||
protected DataCommunicatorClientRpc rpc; | |||
protected DataSource<T> dataSource; | |||
protected DataSource<T, ?> dataSource; | |||
private DataKeyMapper<T> keyMapper; | |||
private boolean reset = false; | |||
private final Set<T> updatedData = new HashSet<T>(); | |||
private Range pushRows = Range.withLength(0, 40); | |||
public DataCommunicator(DataSource<T> dataSource) { | |||
public DataCommunicator(DataSource<T, ?> dataSource) { | |||
addDataGenerator(handler); | |||
this.dataSource = dataSource; | |||
rpc = getRpcProxy(DataCommunicatorClientRpc.class); |
@@ -33,9 +33,18 @@ import com.vaadin.tokka.event.Registration; | |||
* @param <T> | |||
* data type | |||
*/ | |||
public interface DataSource<T> extends Function<Object, Stream<T>>, | |||
public interface DataSource<T, SORT> extends Function<Object, Stream<T>>, | |||
Serializable { | |||
/** | |||
* Sets a default sorting order to the data source. | |||
* | |||
* @param sortOrder | |||
* an object providing the needed sorting information | |||
* @return new data source with modified sorting | |||
*/ | |||
DataSource<T, SORT> sortingBy(SORT sortOrder); | |||
/** | |||
* This method creates a new {@link InMemoryDataSource} from a given | |||
* Collection. The InMemoryDataSource creates a protective List copy of all |
@@ -17,6 +17,7 @@ package com.vaadin.tokka.server.communication.data; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import java.util.function.Function; | |||
import java.util.stream.Stream; | |||
@@ -27,7 +28,7 @@ import java.util.stream.Stream; | |||
* @param <T> | |||
* data type | |||
*/ | |||
public class InMemoryDataSource<T> implements DataSource<T> { | |||
public class InMemoryDataSource<T> implements DataSource<T, Comparator<T>> { | |||
// FIXME: Missing Query object | |||
private Function<Object, Stream<T>> request; | |||
@@ -44,8 +45,26 @@ public class InMemoryDataSource<T> implements DataSource<T> { | |||
request = query -> backend.stream(); | |||
} | |||
/** | |||
* Chaining constructor for making modified {@link InMemoryDataSource}s. | |||
* This Constructor is used internally for making sorted and filtered | |||
* variants of a base data source with actual data. | |||
* | |||
* @param request | |||
* request for the new data source | |||
*/ | |||
protected InMemoryDataSource(Function<Object, Stream<T>> request) { | |||
this.request = request; | |||
} | |||
@Override | |||
public Stream<T> apply(Object query) { | |||
return request.apply(query); | |||
} | |||
@Override | |||
public DataSource<T, Comparator<T>> sortingBy(Comparator<T> sortOrder) { | |||
return new InMemoryDataSource<T>(q -> request.apply(q) | |||
.sorted(sortOrder)); | |||
} | |||
} |
@@ -35,7 +35,7 @@ public interface Listing<T> extends Serializable { | |||
* @param data | |||
* data source | |||
*/ | |||
void setDataSource(DataSource<T> data); | |||
void setDataSource(DataSource<T, ?> data); | |||
/** | |||
* Sets the options available for this Listing. | |||
@@ -62,7 +62,7 @@ public interface Listing<T> extends Serializable { | |||
* | |||
* @return data source | |||
*/ | |||
DataSource<T> getDataSource(); | |||
DataSource<T, ?> getDataSource(); | |||
/** | |||
* Gets the {@link SelectionModel} for this Listing. |
@@ -26,7 +26,7 @@ import com.vaadin.tokka.ui.components.AbstractListing; | |||
public class Grid<T> extends AbstractListing<T> { | |||
private DataSource<T> dataSource; | |||
private DataSource<T, ?> dataSource; | |||
private Map<String, Column<T, ?>> columns = new LinkedHashMap<>(); | |||
public Grid() { | |||
@@ -34,13 +34,13 @@ public class Grid<T> extends AbstractListing<T> { | |||
} | |||
@Override | |||
public void setDataSource(DataSource<T> data) { | |||
public void setDataSource(DataSource<T, ?> data) { | |||
this.dataSource = data; | |||
setDataCommunicator(new DataCommunicator<>(data)); | |||
} | |||
@Override | |||
public DataSource<T> getDataSource() { | |||
public DataSource<T, ?> getDataSource() { | |||
return dataSource; | |||
} | |||
@@ -28,7 +28,7 @@ import elemental.json.JsonObject; | |||
public class NativeSelect<T> extends AbstractListing<T> { | |||
private DataSource<T> dataSource; | |||
private DataSource<T, ?> dataSource; | |||
private Function<T, String> nameProvider = T::toString; | |||
public NativeSelect() { | |||
@@ -47,13 +47,13 @@ public class NativeSelect<T> extends AbstractListing<T> { | |||
}); | |||
} | |||
public NativeSelect(DataSource<T> dataSource) { | |||
public NativeSelect(DataSource<T, ?> dataSource) { | |||
this(); | |||
setDataSource(dataSource); | |||
} | |||
@Override | |||
public void setDataSource(DataSource<T> data) { | |||
public void setDataSource(DataSource<T, ?> data) { | |||
dataSource = data; | |||
if (dataSource != null) { | |||
setDataCommunicator(new DataCommunicator<>(dataSource)); | |||
@@ -63,7 +63,7 @@ public class NativeSelect<T> extends AbstractListing<T> { | |||
} | |||
@Override | |||
public DataSource<T> getDataSource() { | |||
public DataSource<T, ?> getDataSource() { | |||
return dataSource; | |||
} | |||
} |
@@ -2,10 +2,11 @@ package com.vaadin.tokka.data.datasource; | |||
import static org.junit.Assert.assertTrue; | |||
import java.util.ArrayList; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import java.util.stream.Stream; | |||
import java.util.stream.Collectors; | |||
import org.junit.Assert; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
@@ -14,30 +15,12 @@ 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(); | |||
data = StrBean.generateRandomBeans(100); | |||
dataSource = DataSource.create(data); | |||
} | |||
@@ -46,10 +29,47 @@ public class InMemoryDataSourceTest { | |||
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; | |||
@Test | |||
public void testSortByComparatorListsDiffer() { | |||
Comparator<StrBean> comp = Comparator.comparing(StrBean::getValue) | |||
.thenComparing(StrBean::getRandomNumber) | |||
.thenComparing(StrBean::getId); | |||
List<StrBean> list = dataSource.sortingBy(comp).apply(null) | |||
.collect(Collectors.toList()); | |||
// First value in data is { Xyz, 10, 100 } which should be last in list | |||
Assert.assertNotEquals("First value should not match", data.get(0), | |||
list.get(0)); | |||
data.sort(comp); | |||
for (int i = 0; i < data.size(); ++i) { | |||
Assert.assertEquals("Sorting result differed", data.get(i), | |||
list.get(i)); | |||
} | |||
} | |||
@Test | |||
public void testDefatulSortWithSpecifiedPostSort() { | |||
Comparator<StrBean> comp = Comparator.comparing(StrBean::getValue) | |||
.thenComparing(Comparator.comparing(StrBean::getId).reversed()); | |||
List<StrBean> list = dataSource.sortingBy(comp).apply(null) | |||
// The sort here should come e.g from a Component | |||
.sorted(Comparator.comparing(StrBean::getRandomNumber)) | |||
.collect(Collectors.toList()); | |||
for (int i = 1; i < list.size(); ++i) { | |||
StrBean prev = list.get(i - 1); | |||
StrBean cur = list.get(i); | |||
// Test specific sort | |||
Assert.assertTrue(prev.getRandomNumber() <= cur.getRandomNumber()); | |||
if (prev.getRandomNumber() == cur.getRandomNumber()) { | |||
// Test default sort | |||
Assert.assertTrue(prev.getValue().compareTo(cur.getValue()) <= 0); | |||
if (prev.getValue().equals(cur.getValue())) { | |||
Assert.assertTrue(prev.getId() > cur.getId()); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
package com.vaadin.tokka.data.datasource; | |||
import java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Random; | |||
class StrBean implements Serializable { | |||
private static String[] values = new String[] { "Foo", "Bar", "Baz" }; | |||
private String value; | |||
private final int id; | |||
private final int randomNumber; | |||
public StrBean(String value, int id, int randomNumber) { | |||
this.value = value; | |||
this.id = id; | |||
this.randomNumber = randomNumber; | |||
} | |||
public String getValue() { | |||
return value; | |||
} | |||
public int getId() { | |||
return id; | |||
} | |||
public int getRandomNumber() { | |||
return randomNumber; | |||
} | |||
public static List<StrBean> generateRandomBeans(int max) { | |||
List<StrBean> data = new ArrayList<StrBean>(); | |||
Random r = new Random(13337); | |||
data.add(new StrBean("Xyz", 10, max)); | |||
for (int i = 0; i < max - 1; ++i) { | |||
data.add(new StrBean(values[r.nextInt(values.length)], i, r | |||
.nextInt(10))); | |||
} | |||
return data; | |||
} | |||
@Override | |||
public String toString() { | |||
return "{ " + value + ", " + randomNumber + ", " + id + " }"; | |||
} | |||
} |
@@ -29,16 +29,16 @@ public class AbstractListingTest { | |||
AbstractListing<String> testComponent = new AbstractListing<String>() { | |||
DataSource<String> data; | |||
DataSource<String, ?> data; | |||
@Override | |||
public void setDataSource(DataSource<String> data) { | |||
public void setDataSource(DataSource<String, ?> data) { | |||
this.data = data; | |||
setDataCommunicator(new DataCommunicator<>(data)); | |||
} | |||
@Override | |||
public DataSource<String> getDataSource() { | |||
public DataSource<String, ?> getDataSource() { | |||
return data; | |||
} | |||
}; |
@@ -1,6 +1,7 @@ | |||
package com.vaadin.tokka.tests.components; | |||
import java.util.ArrayList; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import java.util.Random; | |||
@@ -80,7 +81,7 @@ public class ListingTestUI extends AbstractTestUI { | |||
.getSelectionModel().getSelected() | |||
.forEach(s -> Notification.show(s)))); | |||
hLayout.addComponent(new Button("Random select", e -> { | |||
DataSource<String> ds = select.getDataSource(); | |||
DataSource<String, ?> ds = select.getDataSource(); | |||
int skip = r.nextInt((int) ds.apply(null).count()); | |||
ds.apply(null).skip(skip).findFirst() | |||
.ifPresent(select.getSelectionModel()::select); | |||
@@ -100,7 +101,8 @@ public class ListingTestUI extends AbstractTestUI { | |||
grid.addColumn("String Value", Bean::getValue); | |||
grid.addColumn("Integer Value", Bean::getIntVal); | |||
grid.addColumn("toString", Bean::toString); | |||
grid.setDataSource(DataSource.create(Bean.generateRandomBeans())); | |||
grid.setDataSource(DataSource.create(Bean.generateRandomBeans()) | |||
.sortingBy(Comparator.comparing(Bean::getValue))); | |||
addComponent(new Button("Toggle Grid Selection", | |||
new Button.ClickListener() { |