diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-07-02 17:34:27 +0300 |
---|---|---|
committer | Henri Sara <hesara@vaadin.com> | 2015-07-10 11:11:32 +0000 |
commit | 40dcbc3cfaa438c9b879720c9012331dd85ca694 (patch) | |
tree | 52afe832e37b50ca8fbe7b67f7ce35acb89613ba /server/src/com/vaadin/data | |
parent | 4fce93896627b862587533e4bd3b71b0e7a3a6b2 (diff) | |
download | vaadin-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.java | 49 | ||||
-rw-r--r-- | server/src/com/vaadin/data/RpcDataProviderExtension.java | 220 |
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 ⇆ 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); } } |