Browse Source

Add basic sorting implementation and API

Change-Id: Ic1fded7f26e3f63c234c6e5bebf8f8fed22e6365
feature/vaadin8-book
Teemu Suo-Anttila 7 years ago
parent
commit
a3c0378df7

+ 2
- 2
server/src/main/java/com/vaadin/tokka/server/communication/data/DataCommunicator.java View File

@@ -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);

+ 10
- 1
server/src/main/java/com/vaadin/tokka/server/communication/data/DataSource.java View File

@@ -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

+ 20
- 1
server/src/main/java/com/vaadin/tokka/server/communication/data/InMemoryDataSource.java View File

@@ -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));
}
}

+ 2
- 2
server/src/main/java/com/vaadin/tokka/ui/components/Listing.java View File

@@ -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.

+ 3
- 3
server/src/main/java/com/vaadin/tokka/ui/components/grid/Grid.java View File

@@ -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;
}


+ 4
- 4
server/src/main/java/com/vaadin/tokka/ui/components/nativeselect/NativeSelect.java View File

@@ -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;
}
}

+ 45
- 25
server/src/test/java/com/vaadin/tokka/data/datasource/InMemoryDataSourceTest.java View File

@@ -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());
}
}
}
}
}

+ 49
- 0
server/src/test/java/com/vaadin/tokka/data/datasource/StrBean.java View File

@@ -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 + " }";
}
}

+ 3
- 3
server/src/test/java/com/vaadin/tokka/ui/components/AbstractListingTest.java View File

@@ -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;
}
};

+ 4
- 2
uitest/src/main/java/com/vaadin/tokka/tests/components/ListingTestUI.java View File

@@ -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() {

Loading…
Cancel
Save