Bladeren bron

Split SimpleDataProvider from DataProvider super class

Change-Id: Ib486553fa2f0f9d17de9012413b2647b73c07822
feature/databinding
Teemu Suo-Anttila 8 jaren geleden
bovenliggende
commit
84d9b40c7b

+ 2
- 2
client/src/com/vaadin/client/connectors/data/typed/DataSourceConnector.java Bestand weergeven

@@ -27,7 +27,7 @@ import com.vaadin.client.ServerConnector;
import com.vaadin.client.data.HasDataSource;
import com.vaadin.client.extensions.AbstractExtensionConnector;
import com.vaadin.client.widget.grid.datasources.ListDataSource;
import com.vaadin.server.communication.data.typed.DataProvider;
import com.vaadin.server.communication.data.typed.SimpleDataProvider;
import com.vaadin.shared.data.DataProviderClientRpc;
import com.vaadin.shared.data.DataProviderConstants;
import com.vaadin.shared.data.DataRequestRpc;
@@ -43,7 +43,7 @@ import elemental.json.JsonObject;
*
* @since
*/
@Connect(DataProvider.class)
@Connect(SimpleDataProvider.class)
public class DataSourceConnector extends AbstractExtensionConnector {

private Map<String, JsonObject> keyToJson = new HashMap<String, JsonObject>();

+ 30
- 148
server/src/com/vaadin/server/communication/data/typed/DataProvider.java Bestand weergeven

@@ -32,17 +32,14 @@ import elemental.json.JsonArray;
import elemental.json.JsonObject;

/**
* DataProvider for Collections. This class takes care of sending data objects
* stored in a Collection from the server-side to the client-side. It uses
* {@link TypedDataGenerator}s to write a {@link JsonObject} representing each
* data object.
* <p>
* This is an implementation that does not provide any kind of lazy loading. All
* data is sent to the client-side on the initial client response.
* DataProvider base class. This class is the base for all DataProvider
* communication implementations. It uses {@link TypedDataGenerator}s to write
* {@link JsonObject}s representing each data object to be sent to the
* client-side.
*
* @since
*/
public class DataProvider<T> extends AbstractExtension {
public abstract class DataProvider<T> extends AbstractExtension {

/**
* Creates the appropriate type of DataProvider based on the type of
@@ -52,6 +49,9 @@ public class DataProvider<T> extends AbstractExtension {
* with the newly created DataProvider. The user should <strong>not</strong>
* call the {@link #extend(com.vaadin.server.AbstractClientConnector)}
* method explicitly.
* <p>
* TODO: Actually use different DataProviders and provide an API for the
* back end to inform changes back.
*
* @param data
* collection of data objects
@@ -59,9 +59,9 @@ public class DataProvider<T> extends AbstractExtension {
* component to extend with the data provider
* @return created data provider
*/
public static <V> DataProvider<V> create(Collection<V> data,
public static <V> SimpleDataProvider<V> create(Collection<V> data,
AbstractComponent component) {
DataProvider<V> dataProvider = new DataProvider<V>(data);
SimpleDataProvider<V> dataProvider = new SimpleDataProvider<V>(data);
dataProvider.extend(component);
return dataProvider;
}
@@ -172,85 +172,21 @@ public class DataProvider<T> extends AbstractExtension {
}
}

/**
* Simple implementation of collection data provider communication. All data
* is sent by server automatically and no data is requested by client.
*/
protected class DataRequestRpcImpl implements DataRequestRpc {

@Override
public void requestRows(int firstRowIndex, int numberOfRows,
int firstCachedRowIndex, int cacheSize) {
throw new UnsupportedOperationException(
"Collection data provider sends all data from server."
+ " It does not expect client to request anything.");
}

@Override
public void dropRows(JsonArray keys) {
for (int i = 0; i < keys.length(); ++i) {
handler.dropActiveData(keys.getString(i));
}

// Use the whole data as the ones sent to the client.
handler.cleanUp(data);
}
}

private Collection<TypedDataGenerator<T>> generators = new LinkedHashSet<TypedDataGenerator<T>>();
private boolean reset = false;
private final Set<T> updatedData = new HashSet<T>();
protected ActiveDataHandler handler = new ActiveDataHandler();
protected DataProviderClientRpc rpc;

private Collection<T> data;
private DataProviderClientRpc rpc;
// TODO: Allow customizing the used key mapper
private DataKeyMapper<T> keyMapper = new KeyMapper<T>();
private ActiveDataHandler handler;

/**
* Creates a new DataProvider with the given Collection.
*
* @param data
* collection of data to use
*/
protected DataProvider(Collection<T> data) {
this.data = data;
// TODO: Add a "BackEnd" API
// protected BackEnd data;

protected DataProvider() {
addDataGenerator(handler);
rpc = getRpcProxy(DataProviderClientRpc.class);
registerRpc(createRpc());
handler = new ActiveDataHandler();
addDataGenerator(handler);
}

/**
* 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 || reset) {
getRpcProxy(DataProviderClientRpc.class).resetSize(data.size());
pushData(0, data);
reset = false;
updatedData.clear();
}

if (updatedData.isEmpty()) {
return;
}

JsonArray dataArray = Json.createArray();
int i = 0;
for (T data : updatedData) {
dataArray.set(i++, getDataObject(data));
}
rpc.updateData(dataArray);
}

/**
* Adds a TypedDataGenerator to this DataProvider.
* Adds a {@link TypedDataGenerator} to this {@link DataProvider}.
*
* @param generator
* typed data generator
@@ -260,7 +196,7 @@ public class DataProvider<T> extends AbstractExtension {
}

/**
* Removes a TypedDataGenerator from this DataProvider.
* Removes a {@link TypedDataGenerator} from this {@link DataProvider}.
*
* @param generator
* typed data generator
@@ -270,7 +206,7 @@ public class DataProvider<T> extends AbstractExtension {
}

/**
* Sends given data collection to the client-side.
* Sends given collection of data objects to the client-side.
*
* @param firstIndex
* first index of pushed data
@@ -291,18 +227,18 @@ public class DataProvider<T> extends AbstractExtension {
}

/**
* Creates the JsonObject for given item. This method calls all data
* generators for this item.
* Creates the JsonObject for given data object. This method calls all data
* generators for it.
*
* @param item
* item to be made into a json object
* @return json object representing the item
* @param data
* data object to be made into a json object
* @return json object representing the data object
*/
protected JsonObject getDataObject(T item) {
protected JsonObject getDataObject(T data) {
JsonObject dataObject = Json.createObject();

for (TypedDataGenerator<T> generator : generators) {
generator.generateData(item, dataObject);
generator.generateData(data, dataObject);
}

return dataObject;
@@ -329,70 +265,16 @@ public class DataProvider<T> extends AbstractExtension {
}

/**
* Gets the {@link DataKeyMapper} instance used by this {@link DataProvider}
* Gets the {@link DataKeyMapper} used by this {@link DataProvider}.
*
* @return key mapper
*/
public DataKeyMapper<T> getKeyMapper() {
return keyMapper;
}
protected abstract DataKeyMapper<T> getKeyMapper();

/**
* Creates an instance of DataRequestRpc. By default it is
* {@link DataRequestRpcImpl}.
* Creates a {@link DataRequestRpc} instance.
*
* @return data request rpc implementation
*/
protected DataRequestRpc createRpc() {
return new DataRequestRpcImpl();
}

/**
* Informs the DataProvider that a data object has been added. It is assumed
* to be the last object in the collection.
*
* @param data
* data object added to collection
*/
public void add(T data) {
rpc.add(getDataObject(data));
}

/**
* Informs the DataProvider that a data object has been removed.
*
* @param data
* data object removed from collection
*/
public void remove(T data) {
if (handler.getActiveData().contains(data)) {
rpc.drop(getKeyMapper().key(data));
}
}

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

reset = true;
markAsDirty();
}

/**
* Informs the DataProvider that a data object has been updated.
*
* @param data
* updated data object
*/
public void refresh(T data) {
if (updatedData.isEmpty()) {
markAsDirty();
}

updatedData.add(data);
}
protected abstract DataRequestRpc createRpc();
}

+ 167
- 0
server/src/com/vaadin/server/communication/data/typed/SimpleDataProvider.java Bestand weergeven

@@ -0,0 +1,167 @@
/*
* 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.server.communication.data.typed;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import com.vaadin.shared.data.DataProviderClientRpc;
import com.vaadin.shared.data.DataRequestRpc;

import elemental.json.Json;
import elemental.json.JsonArray;

/**
* DataProvider for Collections. This class takes care of sending data objects
* stored in a Collection from the server-side to the client-side.
* <p>
* This is an implementation that does not provide any kind of lazy loading. All
* data is sent to the client-side on the initial client response.
*
* @since
*/
public class SimpleDataProvider<T> extends DataProvider<T> {

/**
* Simple implementation of collection data provider communication. All data
* is sent by server automatically and no data is requested by client.
*/
protected class SimpleDataRequestRpc implements DataRequestRpc {

@Override
public void requestRows(int firstRowIndex, int numberOfRows,
int firstCachedRowIndex, int cacheSize) {
throw new UnsupportedOperationException(
"Collection data provider sends all data from server."
+ " It does not expect client to request anything.");
}

@Override
public void dropRows(JsonArray keys) {
for (int i = 0; i < keys.length(); ++i) {
handler.dropActiveData(keys.getString(i));
}

// Use the whole data as the ones sent to the client.
handler.cleanUp(data);
}
}

private boolean reset = false;
private final Set<T> updatedData = new HashSet<T>();

private Collection<T> data;
// TODO: Allow customizing the used key mapper
private DataKeyMapper<T> keyMapper = new KeyMapper<T>();

/**
* Creates a new DataProvider with the given Collection.
*
* @param data
* collection of data to use
*/
protected SimpleDataProvider(Collection<T> data) {
this.data = data;
}

/**
* 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 || reset) {
getRpcProxy(DataProviderClientRpc.class).resetSize(data.size());
pushData(0, data);
reset = false;
updatedData.clear();
}

if (updatedData.isEmpty()) {
return;
}

JsonArray dataArray = Json.createArray();
int i = 0;
for (T data : updatedData) {
dataArray.set(i++, getDataObject(data));
}
rpc.updateData(dataArray);
}

@Override
protected DataKeyMapper<T> getKeyMapper() {
return keyMapper;
}

/**
* Informs the DataProvider that a data object has been added. It is assumed
* to be the last object in the collection.
*
* @param data
* data object added to collection
*/
public void add(T data) {
rpc.add(getDataObject(data));
}

/**
* Informs the DataProvider that a data object has been removed.
*
* @param data
* data object removed from collection
*/
public void remove(T data) {
if (handler.getActiveData().contains(data)) {
rpc.drop(getKeyMapper().key(data));
}
}

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

reset = true;
markAsDirty();
}

/**
* Informs the DataProvider that a data object has been updated.
*
* @param data
* updated data object
*/
public void refresh(T data) {
if (updatedData.isEmpty()) {
markAsDirty();
}

updatedData.add(data);
}

@Override
protected DataRequestRpc createRpc() {
return new SimpleDataRequestRpc();
}

}

+ 5
- 1
uitest/src/com/vaadin/tests/dataprovider/DummyDataProviderUI.java Bestand weergeven

@@ -25,6 +25,7 @@ import java.util.Random;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.communication.data.typed.DataProvider;
import com.vaadin.server.communication.data.typed.SimpleDataProvider;
import com.vaadin.server.communication.data.typed.TypedDataGenerator;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.tests.fieldgroup.ComplexPerson;
@@ -42,7 +43,7 @@ public class DummyDataProviderUI extends AbstractTestUI {

public static class DummyDataComponent extends AbstractComponent {

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

public DummyDataComponent(Collection<ComplexPerson> data) {
@@ -70,18 +71,21 @@ public class DummyDataProviderUI extends AbstractTestUI {
}

void addItem(ComplexPerson person) {
// TODO: This should be in the back end implementation
if (data.add(person)) {
dataProvider.add(person);
}
}

void removeItem(ComplexPerson person) {
// TODO: This should be in the back end implementation
if (data.remove(person)) {
dataProvider.remove(person);
}
}

public void sort(Comparator<ComplexPerson> comparator) {
// TODO: This should be in the back end implementation
Collections.sort(data, comparator);
dataProvider.reset();
}

Laden…
Annuleren
Opslaan