Browse Source

Add simple support for generic reset for data to DataProvider

Adds a simple test that sorts the data and verifies that the content
does not actually change with just sorting.

Change-Id: I0d8889694a98da1d55e0335714f63abaedb5684a
feature/databinding
Teemu Suo-Anttila 8 years ago
parent
commit
e25dd72efe

+ 2
- 1
client/src/com/vaadin/client/connectors/data/typed/DataSourceConnector.java View File

@@ -59,7 +59,8 @@ public class DataSourceConnector extends AbstractExtensionConnector {
public void resetSize(long size) {
ds.asList().clear();
// Inform the server-side that all keys are now dropped.
for (String key : keyToJson.keySet()) {
Set<String> keySet = new HashSet<String>(keyToJson.keySet());
for (String key : keySet) {
dropKey(key);
}
sendDroppedKeys();

+ 19
- 5
server/src/com/vaadin/server/communication/data/typed/DataProvider.java View File

@@ -197,8 +197,10 @@ public class DataProvider<T> extends AbstractExtension {
}
}

private Collection<T> data;
private Collection<TypedDataGenerator<T>> generators = new LinkedHashSet<TypedDataGenerator<T>>();
private boolean reset = false;

private Collection<T> data;
private DataProviderClientRpc rpc;
// TODO: Allow customizing the used key mapper
private DataKeyMapper<T> keyMapper = new KeyMapper<T>();
@@ -220,17 +222,17 @@ public class DataProvider<T> extends AbstractExtension {
}

/**
* Initially we need to push all the data to the client.
*
* TODO: The same is true for unknown size changes.
* Initially and in the case of a reset all data should be pushed to the
* client.
*/
@Override
public void beforeClientResponse(boolean initial) {
super.beforeClientResponse(initial);

if (initial) {
if (initial || reset) {
getRpcProxy(DataProviderClientRpc.class).resetSize(data.size());
pushData(0, data);
reset = false;
}
}

@@ -355,4 +357,16 @@ public class DataProvider<T> extends AbstractExtension {
}
}

/**
* Informs the DataProvider that the collection has changed.
*/
public void reset() {
if (reset) {
return;
}

reset = true;
markAsDirty();
}

}

+ 97
- 7
uitest/src/com/vaadin/tests/dataprovider/DummyDataProviderTest.java View File

@@ -17,7 +17,11 @@ package com.vaadin.tests.dataprovider;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.junit.Test;
@@ -25,6 +29,7 @@ import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import com.vaadin.shared.data.DataProviderConstants;
import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.tests.fieldgroup.ComplexPerson;
import com.vaadin.tests.tb3.SingleBrowserTest;

@@ -33,6 +38,32 @@ import elemental.json.JsonObject;

public class DummyDataProviderTest extends SingleBrowserTest {

// Each test uses a set of person objects (generated json) that is supposed
// to match the data sent to the client-side.
private List<JsonObject> personObjects = new ArrayList<JsonObject>();
// Persons are created exactly the same way as in the test, so we should
// have identical data.
private List<ComplexPerson> persons = DummyDataProviderUI.createPersons(
DummyDataProviderUI.PERSON_COUNT, new Random(
DummyDataProviderUI.RANDOM_SEED));
// For each person we generate a string key, that should match the one
// DataProvider gives to it.
private Map<ComplexPerson, String> personToKeyMap = new HashMap<ComplexPerson, String>();

{
int key = 0;
for (ComplexPerson p : persons) {
personToKeyMap.put(p, "" + (++key));
}
}

@Override
public void setup() throws Exception {
super.setup();

setDebug(true);
}

@Override
protected Class<?> getUIClass() {
return DummyDataProviderUI.class;
@@ -40,9 +71,7 @@ public class DummyDataProviderTest extends SingleBrowserTest {

@Test
public void testVerifyJsonContent() {
Random r = new Random(DummyDataProviderUI.RANDOM_SEED);
List<ComplexPerson> persons = DummyDataProviderUI.createPersons(
DummyDataProviderUI.PERSON_COUNT, r);
createPersonObjects();

openTestURL();

@@ -54,13 +83,74 @@ public class DummyDataProviderTest extends SingleBrowserTest {

List<WebElement> personData = labels.subList(1, size);

int key = 0;
for (WebElement e : personData) {
for (int i = 0; i < personData.size(); ++i) {
WebElement e = personData.get(i);
JsonObject j = personObjects.get(i);
assertEquals("Json did not match.", j.toJson(), e.getText());
}

assertNoErrorNotifications();
}

private void createPersonObjects() {
for (ComplexPerson p : persons) {
JsonObject j = Json.createObject();
ComplexPerson p = persons.get(key);
j.put(DataProviderConstants.KEY, "" + (++key));
j.put(DataProviderConstants.KEY, personToKeyMap.get(p));
j.put("name", p.getLastName() + ", " + p.getFirstName());
personObjects.add(j);
}
}

@Test
public void testSortDoesNotChangeContent() {
// Sort our internal data to match the order after sort.
Collections.sort(persons, DummyDataProviderUI.nameComparator);
createPersonObjects();

openTestURL();

$(ButtonElement.class).id("sort").click();

// Second sort would show if any keys got destroyed/recreated.
$(ButtonElement.class).id("sort").click();

int size = DummyDataProviderUI.PERSON_COUNT + 1;
List<WebElement> labels = findElements(By.className("v-label"));

assertEquals("Label count did not match person count", size,
labels.size());

List<WebElement> personData = labels.subList(1, size);

for (int i = 0; i < personData.size(); ++i) {
WebElement e = personData.get(i);
JsonObject j = personObjects.get(i);
assertEquals("Json did not match.", j.toJson(), e.getText());
}

assertNoErrorNotifications();
}

@Test
public void testRemoveWorksAfterSort() {
// Sort our internal data to match the order after sort.
Collections.sort(persons, DummyDataProviderUI.nameComparator);
createPersonObjects();

openTestURL();

$(ButtonElement.class).id("sort").click();

String text = findElements(By.className("v-label")).get(3).getText();
String json = personObjects.get(2).toJson();
assertEquals("Data not sorted", json, text);

$(ButtonElement.class).id("remove").click();

text = findElements(By.className("v-label")).get(3).getText();
json = personObjects.get(3).toJson();
assertEquals("Data not removed", json, text);

assertNoErrorNotifications();
}
}

+ 37
- 3
uitest/src/com/vaadin/tests/dataprovider/DummyDataProviderUI.java View File

@@ -17,6 +17,8 @@ package com.vaadin.tests.dataprovider;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

@@ -41,10 +43,14 @@ public class DummyDataProviderUI extends AbstractTestUI {
public static class DummyDataComponent extends AbstractComponent {

private DataProvider<ComplexPerson> dataProvider;
private Collection<ComplexPerson> data;
private List<ComplexPerson> data;

public DummyDataComponent(Collection<ComplexPerson> data) {
this.data = data;
if (data instanceof List) {
this.data = (List<ComplexPerson>) data;
} else {
this.data = new ArrayList<ComplexPerson>(data);
}
dataProvider = DataProvider.create(data, this);
dataProvider
.addDataGenerator(new TypedDataGenerator<ComplexPerson>() {
@@ -74,10 +80,25 @@ public class DummyDataProviderUI extends AbstractTestUI {
dataProvider.remove(person);
}
}

public void sort(Comparator<ComplexPerson> comparator) {
Collections.sort(data, comparator);
dataProvider.reset();
}
}

public static final int RANDOM_SEED = 1337;
public static final int PERSON_COUNT = 20;
public static final Comparator<ComplexPerson> nameComparator = new Comparator<ComplexPerson>() {

@Override
public int compare(ComplexPerson p1, ComplexPerson p2) {
int fn = p1.getFirstName().compareTo(p2.getFirstName());
int ln = p1.getLastName().compareTo(p2.getLastName());
return fn != 0 ? fn : ln;
}
};

private Random r = new Random(RANDOM_SEED);
private List<ComplexPerson> persons = createPersons(PERSON_COUNT, r);
private DummyDataComponent dummy;
@@ -100,7 +121,20 @@ public class DummyDataProviderUI extends AbstractTestUI {
dummy.addItem(ComplexPerson.create(r));
}
});
addComponent(new HorizontalLayout(add, remove));
Button sort = new Button("Sort content", new ClickListener() {

@Override
public void buttonClick(ClickEvent event) {
dummy.sort(nameComparator);
}
});

// Button Ids
remove.setId("remove");
add.setId("add");
sort.setId("sort");

addComponent(new HorizontalLayout(add, remove, sort));
addComponent(dummy);
}


Loading…
Cancel
Save