summaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin/data
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2015-07-02 17:34:27 +0300
committerHenri Sara <hesara@vaadin.com>2015-07-10 11:11:32 +0000
commit40dcbc3cfaa438c9b879720c9012331dd85ca694 (patch)
tree52afe832e37b50ca8fbe7b67f7ce35acb89613ba /server/src/com/vaadin/data
parent4fce93896627b862587533e4bd3b71b0e7a3a6b2 (diff)
downloadvaadin-framework-40dcbc3cfaa438c9b879720c9012331dd85ca694.tar.gz
vaadin-framework-40dcbc3cfaa438c9b879720c9012331dd85ca694.zip
Refactor RpcDataProviderExtension to use DataGenerators
Change-Id: I8c809b6fac827df730c6622fb6790410c6c5bd81
Diffstat (limited to 'server/src/com/vaadin/data')
-rw-r--r--server/src/com/vaadin/data/DataGenerator.java49
-rw-r--r--server/src/com/vaadin/data/RpcDataProviderExtension.java220
2 files changed, 119 insertions, 150 deletions
diff --git a/server/src/com/vaadin/data/DataGenerator.java b/server/src/com/vaadin/data/DataGenerator.java
new file mode 100644
index 0000000000..f025623a3e
--- /dev/null
+++ b/server/src/com/vaadin/data/DataGenerator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.data;
+
+import java.io.Serializable;
+
+import com.vaadin.ui.Grid.AbstractGridExtension;
+import com.vaadin.ui.Grid.AbstractRenderer;
+
+import elemental.json.JsonObject;
+
+/**
+ * Interface for {@link AbstractGridExtension}s that allows adding data to row
+ * objects being sent to client by the {@link RpcDataProviderExtension}.
+ * <p>
+ * {@link AbstractRenderer} implements this interface to provide encoded data to
+ * client for {@link Renderer}s automatically.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface DataGenerator extends Serializable {
+
+ /**
+ * Adds data to row object for given item and item id being sent to client.
+ *
+ * @param itemId
+ * item id of item
+ * @param item
+ * item being sent to client
+ * @param rowData
+ * row object being sent to client
+ */
+ public void generateData(Object itemId, Item item, JsonObject rowData);
+
+}
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java
index 9d18736ba8..71b597ff1d 100644
--- a/server/src/com/vaadin/data/RpcDataProviderExtension.java
+++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java
@@ -23,11 +23,9 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.logging.Logger;
import com.google.gwt.thirdparty.guava.common.collect.BiMap;
import com.google.gwt.thirdparty.guava.common.collect.HashBiMap;
@@ -43,10 +41,8 @@ import com.vaadin.data.Container.ItemSetChangeNotifier;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Property.ValueChangeNotifier;
-import com.vaadin.data.util.converter.Converter;
import com.vaadin.server.AbstractExtension;
import com.vaadin.server.ClientConnector;
-import com.vaadin.server.KeyMapper;
import com.vaadin.shared.data.DataProviderRpc;
import com.vaadin.shared.data.DataRequestRpc;
import com.vaadin.shared.ui.grid.DetailsConnectorChange;
@@ -56,13 +52,9 @@ import com.vaadin.shared.ui.grid.Range;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
import com.vaadin.ui.Grid;
-import com.vaadin.ui.Grid.CellReference;
-import com.vaadin.ui.Grid.CellStyleGenerator;
import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.DetailsGenerator;
import com.vaadin.ui.Grid.RowReference;
-import com.vaadin.ui.Grid.RowStyleGenerator;
-import com.vaadin.ui.renderers.Renderer;
import elemental.json.Json;
import elemental.json.JsonArray;
@@ -93,7 +85,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
* itemId &lrarr; key mapping is not needed anymore. In other words, this
* doesn't leak memory.
*/
- public class DataProviderKeyMapper implements Serializable {
+ public class DataProviderKeyMapper implements Serializable, DataGenerator {
private final BiMap<Object, String> itemIdToKey = HashBiMap.create();
private Set<Object> pinnedItemIds = new HashSet<Object>();
private long rollingIndex = 0;
@@ -125,7 +117,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
for (Object itemId : itemSet) {
itemIdToKey.put(itemId, getKey(itemId));
- if (visibleDetails.contains(itemId)) {
+ if (detailComponentManager.visibleDetails.contains(itemId)) {
detailComponentManager.createDetails(itemId,
indexOf(itemId));
}
@@ -280,6 +272,16 @@ public class RpcDataProviderExtension extends AbstractExtension {
public boolean isPinned(Object itemId) {
return pinnedItemIds.contains(itemId);
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since
+ */
+ @Override
+ public void generateData(Object itemId, Item item, JsonObject rowData) {
+ rowData.put(GridState.JSONKEY_ROWKEY, getKey(itemId));
+ }
}
/**
@@ -601,7 +603,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
* @since 7.5.0
* @author Vaadin Ltd
*/
- public static final class DetailComponentManager implements Serializable {
+ public static final class DetailComponentManager implements DataGenerator {
/**
* This map represents all the components that have been requested for
* each item id.
@@ -649,6 +651,12 @@ public class RpcDataProviderExtension extends AbstractExtension {
*/
private final Map<Object, Integer> emptyDetails = Maps.newHashMap();
+ /**
+ * This map represents all the details that are user-defined as visible.
+ * This does not reflect the status in the DOM.
+ */
+ private Set<Object> visibleDetails = new HashSet<Object>();
+
private Grid grid;
/**
@@ -856,6 +864,18 @@ public class RpcDataProviderExtension extends AbstractExtension {
}
this.grid = grid;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since
+ */
+ @Override
+ public void generateData(Object itemId, Item item, JsonObject rowData) {
+ if (visibleDetails.contains(itemId)) {
+ rowData.put(GridState.JSONKEY_DETAILS_VISIBLE, true);
+ }
+ }
}
private final Indexed container;
@@ -939,14 +959,9 @@ public class RpcDataProviderExtension extends AbstractExtension {
private final DataProviderKeyMapper keyMapper = new DataProviderKeyMapper();
- private KeyMapper<Object> columnKeys;
-
/** RpcDataProvider should send the current cache again. */
private boolean refreshCache = false;
- private RowReference rowReference;
- private CellReference cellReference;
-
/** Set of updated item ids */
private Set<Object> updatedItemIds = new LinkedHashSet<Object>();
@@ -959,14 +974,10 @@ public class RpcDataProviderExtension extends AbstractExtension {
/** Size possibly changed with a bare ItemSetChangeEvent */
private boolean bareItemSetTriggeredSizeChange = false;
- /**
- * This map represents all the details that are user-defined as visible.
- * This does not reflect the status in the DOM.
- */
- private Set<Object> visibleDetails = new HashSet<Object>();
-
private final DetailComponentManager detailComponentManager = new DetailComponentManager();
+ private Set<DataGenerator> dataGenerators = new LinkedHashSet<DataGenerator>();
+
/**
* Creates a new data provider using the given container.
*
@@ -1006,6 +1017,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
.addItemSetChangeListener(itemListener);
}
+ addDataGenerator(keyMapper);
+ addDataGenerator(detailComponentManager);
}
/**
@@ -1090,73 +1103,14 @@ public class RpcDataProviderExtension extends AbstractExtension {
private JsonValue getRowData(Collection<Column> columns, Object itemId) {
Item item = container.getItem(itemId);
- JsonObject rowData = Json.createObject();
-
- Grid grid = getGrid();
-
- for (Column column : columns) {
- Object propertyId = column.getPropertyId();
-
- Object propertyValue = item.getItemProperty(propertyId).getValue();
- JsonValue encodedValue = encodeValue(propertyValue,
- column.getRenderer(), column.getConverter(),
- grid.getLocale());
-
- rowData.put(columnKeys.key(propertyId), encodedValue);
- }
-
final JsonObject rowObject = Json.createObject();
- rowObject.put(GridState.JSONKEY_DATA, rowData);
- rowObject.put(GridState.JSONKEY_ROWKEY, keyMapper.getKey(itemId));
-
- if (visibleDetails.contains(itemId)) {
- rowObject.put(GridState.JSONKEY_DETAILS_VISIBLE, true);
- }
-
- rowReference.set(itemId);
-
- CellStyleGenerator cellStyleGenerator = grid.getCellStyleGenerator();
- if (cellStyleGenerator != null) {
- setGeneratedCellStyles(cellStyleGenerator, rowObject, columns);
- }
- RowStyleGenerator rowStyleGenerator = grid.getRowStyleGenerator();
- if (rowStyleGenerator != null) {
- setGeneratedRowStyles(rowStyleGenerator, rowObject);
+ for (DataGenerator dg : dataGenerators) {
+ dg.generateData(itemId, item, rowObject);
}
return rowObject;
}
- private void setGeneratedCellStyles(CellStyleGenerator generator,
- JsonObject rowObject, Collection<Column> columns) {
- JsonObject cellStyles = null;
- for (Column column : columns) {
- Object propertyId = column.getPropertyId();
- cellReference.set(propertyId);
- String style = generator.getStyle(cellReference);
- if (style != null && !style.isEmpty()) {
- if (cellStyles == null) {
- cellStyles = Json.createObject();
- }
-
- String columnKey = columnKeys.key(propertyId);
- cellStyles.put(columnKey, style);
- }
- }
- if (cellStyles != null) {
- rowObject.put(GridState.JSONKEY_CELLSTYLES, cellStyles);
- }
-
- }
-
- private void setGeneratedRowStyles(RowStyleGenerator generator,
- JsonObject rowObject) {
- String rowStyle = generator.getStyle(rowReference);
- if (rowStyle != null && !rowStyle.isEmpty()) {
- rowObject.put(GridState.JSONKEY_ROWSTYLE, rowStyle);
- }
- }
-
/**
* Makes the data source available to the given {@link Grid} component.
*
@@ -1165,13 +1119,38 @@ public class RpcDataProviderExtension extends AbstractExtension {
* @param columnKeys
* the key mapper for columns
*/
- public void extend(Grid component, KeyMapper<Object> columnKeys) {
- this.columnKeys = columnKeys;
+ public void extend(Grid component) {
detailComponentManager.setGrid(component);
super.extend(component);
}
/**
+ * Adds a {@link DataGenerator} for this {@code RpcDataProviderExtension}.
+ * DataGenerators are called when sending row data to client. If given
+ * DataGenerator is already added, this method does nothing.
+ *
+ * @since
+ * @param generator
+ * generator to add
+ */
+ public void addDataGenerator(DataGenerator generator) {
+ dataGenerators.add(generator);
+ }
+
+ /**
+ * Removes a {@link DataGenerator} from this
+ * {@code RpcDataProviderExtension}. If given DataGenerator is not added to
+ * this data provider, this method does nothing.
+ *
+ * @since
+ * @param generator
+ * generator to remove
+ */
+ public void removeDataGenerator(DataGenerator generator) {
+ dataGenerators.remove(generator);
+ }
+
+ /**
* Informs the client side that new rows have been inserted into the data
* source.
*
@@ -1281,11 +1260,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
.removeItemSetChangeListener(itemListener);
}
- } else if (parent instanceof Grid) {
- Grid grid = (Grid) parent;
- rowReference = new RowReference(grid);
- cellReference = new CellReference(rowReference);
- } else {
+ } else if (!(parent instanceof Grid)) {
throw new IllegalStateException(
"Grid is the only accepted parent type");
}
@@ -1322,62 +1297,6 @@ public class RpcDataProviderExtension extends AbstractExtension {
}
/**
- * Converts and encodes the given data model property value using the given
- * converter and renderer. This method is public only for testing purposes.
- *
- * @param renderer
- * the renderer to use
- * @param converter
- * the converter to use
- * @param modelValue
- * the value to convert and encode
- * @param locale
- * the locale to use in conversion
- * @return an encoded value ready to be sent to the client
- */
- public static <T> JsonValue encodeValue(Object modelValue,
- Renderer<T> renderer, Converter<?, ?> converter, Locale locale) {
- Class<T> presentationType = renderer.getPresentationType();
- T presentationValue;
-
- if (converter == null) {
- try {
- presentationValue = presentationType.cast(modelValue);
- } catch (ClassCastException e) {
- if (presentationType == String.class) {
- // If there is no converter, just fallback to using
- // toString().
- // modelValue can't be null as Class.cast(null) will always
- // succeed
- presentationValue = (T) modelValue.toString();
- } else {
- throw new Converter.ConversionException(
- "Unable to convert value of type "
- + modelValue.getClass().getName()
- + " to presentation type "
- + presentationType.getName()
- + ". No converter is set and the types are not compatible.");
- }
- }
- } else {
- assert presentationType.isAssignableFrom(converter
- .getPresentationType());
- @SuppressWarnings("unchecked")
- Converter<T, Object> safeConverter = (Converter<T, Object>) converter;
- presentationValue = safeConverter.convertToPresentation(modelValue,
- safeConverter.getPresentationType(), locale);
- }
-
- JsonValue encodedValue = renderer.encode(presentationValue);
-
- return encodedValue;
- }
-
- private static Logger getLogger() {
- return Logger.getLogger(RpcDataProviderExtension.class.getName());
- }
-
- /**
* Marks a row's details to be visible or hidden.
* <p>
* If that row is currently in the client side's cache, this information
@@ -1394,7 +1313,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
final boolean modified;
if (visible) {
- modified = visibleDetails.add(itemId);
+ modified = detailComponentManager.visibleDetails.add(itemId);
/*
* We don't want to create the component here, since the component
@@ -1405,7 +1324,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
*/
} else {
- modified = visibleDetails.remove(itemId);
+ modified = detailComponentManager.visibleDetails.remove(itemId);
/*
* Here we can try to destroy the component no matter what. The
@@ -1435,7 +1354,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
* visible in the DOM
*/
public boolean isDetailsVisible(Object itemId) {
- return visibleDetails.contains(itemId);
+ return detailComponentManager.visibleDetails.contains(itemId);
}
/**
@@ -1444,7 +1363,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
* @since 7.5.0
*/
public void refreshDetails() {
- for (Object itemId : ImmutableSet.copyOf(visibleDetails)) {
+ for (Object itemId : ImmutableSet
+ .copyOf(detailComponentManager.visibleDetails)) {
detailComponentManager.refresh(itemId);
}
}