aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Paul <henrik@vaadin.com>2014-06-18 16:04:46 +0300
committerHenrik Paul <henrik@vaadin.com>2014-06-26 13:32:23 +0300
commitf4a538019bc6c5abeeb453d9f116088d03d7c32f (patch)
tree669bd2302cde16468bd6dfe5640916ada4bf1249
parent10f7eb04e354a072a04af362f95f831f0656abf7 (diff)
downloadvaadin-framework-f4a538019bc6c5abeeb453d9f116088d03d7c32f.tar.gz
vaadin-framework-f4a538019bc6c5abeeb453d9f116088d03d7c32f.zip
Change row data type from String[] to String (#13334)
Instead of having the data type as one-string-per-column, we now have the entire row encoded as JSON Change-Id: I709b2daa88c516d98203ef463b57257a6647bacd
-rw-r--r--client/src/com/vaadin/client/data/RpcDataSourceConnector.java27
-rw-r--r--client/src/com/vaadin/client/ui/grid/GridConnector.java50
-rw-r--r--client/src/com/vaadin/client/ui/grid/renderers/AbstractRendererConnector.java2
-rw-r--r--server/src/com/vaadin/data/RpcDataProviderExtension.java107
-rw-r--r--shared/src/com/vaadin/shared/data/DataProviderRpc.java22
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridState.java7
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java60
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java42
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java36
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java51
10 files changed, 344 insertions, 60 deletions
diff --git a/client/src/com/vaadin/client/data/RpcDataSourceConnector.java b/client/src/com/vaadin/client/data/RpcDataSourceConnector.java
index fba8c732f6..2b9bf5c90e 100644
--- a/client/src/com/vaadin/client/data/RpcDataSourceConnector.java
+++ b/client/src/com/vaadin/client/data/RpcDataSourceConnector.java
@@ -16,8 +16,12 @@
package com.vaadin.client.data;
-import java.util.List;
+import java.util.ArrayList;
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONParser;
+import com.google.gwt.json.client.JSONValue;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.extensions.AbstractExtensionConnector;
import com.vaadin.client.ui.grid.GridConnector;
@@ -39,7 +43,7 @@ import com.vaadin.shared.ui.grid.Range;
@Connect(com.vaadin.data.RpcDataProviderExtension.class)
public class RpcDataSourceConnector extends AbstractExtensionConnector {
- private final AbstractRemoteDataSource<String[]> dataSource = new AbstractRemoteDataSource<String[]>() {
+ private final AbstractRemoteDataSource<JSONObject> dataSource = new AbstractRemoteDataSource<JSONObject>() {
@Override
protected void requestRows(int firstRowIndex, int numberOfRows) {
Range cached = getCachedRange();
@@ -49,7 +53,7 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector {
}
@Override
- public Object getRowKey(String[] row) {
+ public Object getRowKey(JSONObject row) {
/*
* FIXME will be properly implemented by another patch (Henrik Paul:
* 16.6.2014)
@@ -65,7 +69,22 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector {
registerRpc(DataProviderRpc.class, new DataProviderRpc() {
@Override
- public void setRowData(int firstRow, List<String[]> rows) {
+ public void setRowData(int firstRow, String rowsJson) {
+ JSONValue parsedJson = JSONParser.parseStrict(rowsJson);
+ JSONArray rowArray = parsedJson.isArray();
+ assert rowArray != null : "Was unable to parse JSON into an array: "
+ + parsedJson;
+
+ ArrayList<JSONObject> rows = new ArrayList<JSONObject>(rowArray
+ .size());
+ for (int i = 0; i < rowArray.size(); i++) {
+ JSONValue rowValue = rowArray.get(i);
+ JSONObject rowObject = rowValue.isObject();
+ assert rowObject != null : "Was unable to parse JSON into an object: "
+ + rowValue;
+ rows.add(rowObject);
+ }
+
dataSource.setRowData(firstRow, rows);
}
diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java
index ab304a9214..95b493b451 100644
--- a/client/src/com/vaadin/client/ui/grid/GridConnector.java
+++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java
@@ -24,6 +24,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONValue;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector;
@@ -38,6 +41,10 @@ import com.vaadin.shared.ui.grid.ScrollDestination;
/**
* Connects the client side {@link Grid} widget with the server side
* {@link com.vaadin.ui.components.grid.Grid} component.
+ * <p>
+ * The Grid is typed to JSONObject. The structure of the JSONObject is described
+ * at {@link com.vaadin.shared.data.DataProviderRpc#setRowData(int, List)
+ * DataProviderRpc.setRowData(int, List)}.
*
* @since 7.4
* @author Vaadin Ltd
@@ -49,23 +56,29 @@ public class GridConnector extends AbstractComponentConnector {
* Custom implementation of the custom grid column using a String[] to
* represent the cell value and String as a column type.
*/
- private class CustomGridColumn extends GridColumn<String, String[]> {
+ private class CustomGridColumn extends GridColumn<Object, JSONObject> {
private final String id;
- private AbstractRendererConnector<String> rendererConnector;
+ private AbstractRendererConnector<Object> rendererConnector;
public CustomGridColumn(String id,
- AbstractRendererConnector<String> rendererConnector) {
+ AbstractRendererConnector<Object> rendererConnector) {
super(rendererConnector.getRenderer());
this.rendererConnector = rendererConnector;
this.id = id;
}
@Override
- public String getValue(String[] obj) {
- // TODO this should invoke AbstractRendererConnector.decode
- return obj[resolveCurrentIndexFromState()];
+ public Object getValue(final JSONObject obj) {
+ final JSONValue rowData = obj.get(GridState.JSONKEY_DATA);
+ final JSONArray rowDataArray = rowData.isArray();
+ assert rowDataArray != null : "Was unable to parse JSON into an array: "
+ + rowData;
+
+ final int columnIndex = resolveCurrentIndexFromState();
+ final JSONValue columnValue = rowDataArray.get(columnIndex);
+ return rendererConnector.decode(columnValue);
}
/*
@@ -74,7 +87,7 @@ public class GridConnector extends AbstractComponentConnector {
*
* TODO remove once support for changing renderers is implemented
*/
- private AbstractRendererConnector<String> getRendererConnector() {
+ private AbstractRendererConnector<Object> getRendererConnector() {
return rendererConnector;
}
@@ -97,8 +110,8 @@ public class GridConnector extends AbstractComponentConnector {
@Override
@SuppressWarnings("unchecked")
- public Grid<String[]> getWidget() {
- return (Grid<String[]>) super.getWidget();
+ public Grid<JSONObject> getWidget() {
+ return (Grid<JSONObject>) super.getWidget();
}
@Override
@@ -207,7 +220,7 @@ public class GridConnector extends AbstractComponentConnector {
* The index of the column to update
*/
private void updateColumnFromStateChangeEvent(int columnIndex) {
- GridColumn<?, String[]> column = getWidget().getColumn(columnIndex);
+ GridColumn<?, JSONObject> column = getWidget().getColumn(columnIndex);
GridColumnState columnState = getState().columns.get(columnIndex);
updateColumnFromState(column, columnState);
@@ -226,8 +239,9 @@ public class GridConnector extends AbstractComponentConnector {
*/
private void addColumnFromStateChangeEvent(int columnIndex) {
GridColumnState state = getState().columns.get(columnIndex);
+ @SuppressWarnings("unchecked")
CustomGridColumn column = new CustomGridColumn(state.id,
- ((AbstractRendererConnector<String>) state.rendererConnector));
+ ((AbstractRendererConnector<Object>) state.rendererConnector));
columnIdToColumn.put(state.id, column);
// Adds a column to grid, and registers Grid with the column.
@@ -252,7 +266,7 @@ public class GridConnector extends AbstractComponentConnector {
* @param state
* The state to get the data from
*/
- private static void updateColumnFromState(GridColumn<?, String[]> column,
+ private static void updateColumnFromState(GridColumn<?, JSONObject> column,
GridColumnState state) {
column.setVisible(state.visible);
column.setHeaderCaption(state.header);
@@ -293,23 +307,25 @@ public class GridConnector extends AbstractComponentConnector {
// FIXME When something changes the header/footer rows will be
// re-created. At some point we should optimize this so partial updates
// can be made on the header/footer.
- for (ColumnGroupRow<String[]> row : getWidget().getColumnGroupRows()) {
+ for (ColumnGroupRow<JSONObject> row : getWidget().getColumnGroupRows()) {
getWidget().removeColumnGroupRow(row);
}
for (ColumnGroupRowState rowState : getState().columnGroupRows) {
- ColumnGroupRow<String[]> row = getWidget().addColumnGroupRow();
+ ColumnGroupRow<JSONObject> row = getWidget().addColumnGroupRow();
row.setFooterVisible(rowState.footerVisible);
row.setHeaderVisible(rowState.headerVisible);
for (ColumnGroupState groupState : rowState.groups) {
- List<GridColumn<String, String[]>> columns = new ArrayList<GridColumn<String, String[]>>();
+ List<GridColumn<Object, JSONObject>> columns = new ArrayList<GridColumn<Object, JSONObject>>();
for (String columnId : groupState.columns) {
CustomGridColumn column = columnIdToColumn.get(columnId);
columns.add(column);
}
- ColumnGroup<String[]> group = row.addGroup(columns
- .toArray(new GridColumn[columns.size()]));
+ @SuppressWarnings("unchecked")
+ final GridColumn<?, JSONObject>[] gridColumns = columns
+ .toArray(new GridColumn[columns.size()]);
+ ColumnGroup<JSONObject> group = row.addGroup(gridColumns);
group.setFooterCaption(groupState.footer);
group.setHeaderCaption(groupState.header);
}
diff --git a/client/src/com/vaadin/client/ui/grid/renderers/AbstractRendererConnector.java b/client/src/com/vaadin/client/ui/grid/renderers/AbstractRendererConnector.java
index 236fdbe9f6..b57b674292 100644
--- a/client/src/com/vaadin/client/ui/grid/renderers/AbstractRendererConnector.java
+++ b/client/src/com/vaadin/client/ui/grid/renderers/AbstractRendererConnector.java
@@ -102,8 +102,6 @@ public abstract class AbstractRendererConnector<T> extends
* Decodes the given JSON value into a value of type T so it can be passed
* to the {@link #getRenderer() renderer}.
*
- * TODO This method is currently not called from anywhere
- *
* @param value
* the value to decode
* @return the decoded value of {@code value}
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java
index 79121af6b0..0046b256bb 100644
--- a/server/src/com/vaadin/data/RpcDataProviderExtension.java
+++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java
@@ -17,7 +17,6 @@
package com.vaadin.data;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -26,6 +25,10 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import com.vaadin.data.Container.Indexed;
import com.vaadin.data.Container.Indexed.ItemAddEvent;
import com.vaadin.data.Container.Indexed.ItemRemoveEvent;
@@ -41,6 +44,7 @@ import com.vaadin.server.ClientConnector;
import com.vaadin.shared.data.DataProviderRpc;
import com.vaadin.shared.data.DataProviderState;
import com.vaadin.shared.data.DataRequestRpc;
+import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.ui.components.grid.Grid;
import com.vaadin.ui.components.grid.GridColumn;
@@ -68,8 +72,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
* <ul>
* <li>listening to the currently visible {@link Property Properties'} value
* changes on the server side and sending those back to the client; and
- * <li>attaching and detaching {@link Component Components} from the Vaadin
- * Component hierarchy.
+ * <li>attaching and detaching {@link com.vaadin.ui.Component Components}
+ * from the Vaadin Component hierarchy.
* </ul>
*/
private class ActiveRowHandler implements Serializable {
@@ -191,7 +195,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
* @param removedPropertyIds
* the property ids that have been removed from the container
*/
- public void propertiesRemoved(Collection<Object> removedPropertyIds) {
+ public void propertiesRemoved(@SuppressWarnings("unused")
+ Collection<Object> removedPropertyIds) {
/*
* no-op, for now.
*
@@ -387,31 +392,48 @@ public class RpcDataProviderExtension extends AbstractExtension {
private void pushRows(int firstRow, int numberOfRows) {
List<?> itemIds = container.getItemIds(firstRow, numberOfRows);
Collection<?> propertyIds = container.getContainerPropertyIds();
- List<String[]> rows = new ArrayList<String[]>(itemIds.size());
+ JSONArray rows = new JSONArray();
for (Object itemId : itemIds) {
- rows.add(getRowData(propertyIds, itemId));
+ rows.put(getRowData(propertyIds, itemId));
}
- getRpcProxy(DataProviderRpc.class).setRowData(firstRow, rows);
+ String jsonString = rows.toString();
+ getRpcProxy(DataProviderRpc.class).setRowData(firstRow, jsonString);
}
- private String[] getRowData(Collection<?> propertyIds, Object itemId) {
+ private JSONObject getRowData(Collection<?> propertyIds, Object itemId) {
Item item = container.getItem(itemId);
- String[] row = new String[propertyIds.size()];
- int i = 0;
- final Grid grid = getGrid();
- for (Object propertyId : propertyIds) {
- GridColumn column = grid.getColumn(propertyId);
+ JSONArray rowData = new JSONArray();
+
+ Grid grid = getGrid();
+ try {
+ for (Object propertyId : propertyIds) {
+ GridColumn column = grid.getColumn(propertyId);
- Object propertyValue = item.getItemProperty(propertyId).getValue();
- Object encodedValue = encodeValue(propertyValue,
- column.getRenderer(), column.getConverter(),
- grid.getLocale());
+ Object propertyValue = item.getItemProperty(propertyId)
+ .getValue();
+ Object encodedValue = encodeValue(propertyValue,
+ column.getRenderer(), column.getConverter(),
+ grid.getLocale());
+
+ rowData.put(encodedValue);
+ }
- // TODO Drop string conversion once client supports Objects
- row[i++] = String.valueOf(encodedValue);
+ final JSONObject rowObject = new JSONObject();
+ rowObject.put(GridState.JSONKEY_DATA, rowData);
+ /*
+ * TODO: selection wants to put here something in the lines of:
+ *
+ * rowObject.put(GridState.JSONKEY_ROWKEY, getKey(itemId))
+ *
+ * Henrik Paul: 18.6.2014
+ */
+ return rowObject;
+ } catch (final JSONException e) {
+ throw new RuntimeException("Grid was unable to serialize "
+ + "data for row (this should've been caught "
+ + "eariler by other Grid logic)", e);
}
- return row;
}
@Override
@@ -487,9 +509,10 @@ public class RpcDataProviderExtension extends AbstractExtension {
* roundtrip.
*/
Object itemId = container.getIdByIndex(index);
- String[] row = getRowData(container.getContainerPropertyIds(), itemId);
- getRpcProxy(DataProviderRpc.class).setRowData(index,
- Collections.singletonList(row));
+ JSONObject row = getRowData(container.getContainerPropertyIds(), itemId);
+ JSONArray rowArray = new JSONArray(Collections.singleton(row));
+ String jsonString = rowArray.toString();
+ getRpcProxy(DataProviderRpc.class).setRowData(index, jsonString);
}
@Override
@@ -513,10 +536,11 @@ public class RpcDataProviderExtension extends AbstractExtension {
* Informs this data provider that some of the properties have been removed
* from the container.
* <p>
- * Please note that we could add our own {@link PropertySetChangeListener}
- * to the container, but then we'd need to implement the same bookeeping for
- * finding what's added and removed that Grid already does in its own
- * listener.
+ * Please note that we could add our own
+ * {@link com.vaadin.data.Container.PropertySetChangeListener
+ * PropertySetChangeListener} to the container, but then we'd need to
+ * implement the same bookeeping for finding what's added and removed that
+ * Grid already does in its own listener.
*
* @param removedColumns
* a list of property ids for the removed columns
@@ -529,10 +553,11 @@ public class RpcDataProviderExtension extends AbstractExtension {
* Informs this data provider that some of the properties have been added to
* the container.
* <p>
- * Please note that we could add our own {@link PropertySetChangeListener}
- * to the container, but then we'd need to implement the same bookeeping for
- * finding what's added and removed that Grid already does in its own
- * listener.
+ * Please note that we could add our own
+ * {@link com.vaadin.data.Container.PropertySetChangeListener
+ * PropertySetChangeListener} to the container, but then we'd need to
+ * implement the same bookeeping for finding what's added and removed that
+ * Grid already does in its own listener.
*
* @param addedPropertyIds
* a list of property ids for the added columns
@@ -584,6 +609,24 @@ public class RpcDataProviderExtension extends AbstractExtension {
safeConverter.getPresentationType(), locale);
}
- return renderer.encode(presentationValue);
+ Object encodedValue = renderer.encode(presentationValue);
+
+ /*
+ * because this is a relatively heavy operation, we'll hide this behind
+ * an assert so that the check will be removed in production mode
+ */
+ assert jsonSupports(encodedValue) : "org.json.JSONObject does not know how to serialize objects of type "
+ + encodedValue.getClass().getName();
+ return encodedValue;
+ }
+
+ private static boolean jsonSupports(Object encodedValue) {
+ JSONObject jsonObject = new JSONObject();
+ try {
+ jsonObject.accumulate("test", encodedValue);
+ } catch (JSONException e) {
+ return false;
+ }
+ return true;
}
}
diff --git a/shared/src/com/vaadin/shared/data/DataProviderRpc.java b/shared/src/com/vaadin/shared/data/DataProviderRpc.java
index a2f85159ba..a92ffe0421 100644
--- a/shared/src/com/vaadin/shared/data/DataProviderRpc.java
+++ b/shared/src/com/vaadin/shared/data/DataProviderRpc.java
@@ -16,8 +16,6 @@
package com.vaadin.shared.data;
-import java.util.List;
-
import com.vaadin.shared.communication.ClientRpc;
/**
@@ -31,14 +29,28 @@ public interface DataProviderRpc extends ClientRpc {
/**
* Sends updated row data to a client.
* <p>
- * TODO rowData should be List<Object[]>
+ * rowDataJson represents a JSON array of JSON objects in the following
+ * format:
+ *
+ * <pre>
+ * [{
+ * "d": [COL_1_JSON, COL_2_json, ...]
+ * },
+ * ...
+ * ]
+ * </pre>
+ *
+ * where COL_INDEX is the index of the column (as a string), and COL_n_JSON
+ * is valid JSON of the column's data.
*
* @param firstRowIndex
* the index of the first updated row
- * @param rowData
+ * @param rowDataJson
* the updated row data
+ * @see com.vaadin.shared.ui.grid.GridState#JSONKEY_DATA
+ * @see com.vaadin.ui.components.grid.Renderer#encode(Object)
*/
- public void setRowData(int firstRowIndex, List<String[]> rowData);
+ public void setRowData(int firstRowIndex, String rowDataJson);
/**
* Informs the client to remove row data.
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java
index acb2a48e3c..eceaedd1fc 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridState.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java
@@ -37,6 +37,13 @@ public class GridState extends AbstractComponentState {
*/
public static final double DEFAULT_HEIGHT_BY_ROWS = 10.0d;
+ /**
+ * The key in which a row's data can be found
+ * {@link com.vaadin.shared.data.DataProviderRpc#setRowData(int, List)
+ * DataProviderRpc.setRowData(int, List)}
+ */
+ public static final String JSONKEY_DATA = "d";
+
{
// FIXME Grid currently does not support undefined size
width = "400px";
diff --git a/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java b/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java
new file mode 100644
index 0000000000..7e079e69b7
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java
@@ -0,0 +1,60 @@
+/*
+ * 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.tests.components.grid;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.ui.components.grid.Grid;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class CustomRenderer extends AbstractTestUI {
+
+ private static final Object INT_ARRAY_PROPERTY = "int array";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty(INT_ARRAY_PROPERTY, int[].class,
+ new int[] {});
+
+ Object itemId = new Object();
+ Item item = container.addItem(itemId);
+ @SuppressWarnings("unchecked")
+ Property<int[]> property = item.getItemProperty(INT_ARRAY_PROPERTY);
+ property.setValue(new int[] { 1, 1, 2, 3, 5, 8, 13 });
+
+ Grid grid = new Grid(container);
+ grid.getColumn(INT_ARRAY_PROPERTY).setRenderer(new IntArrayRenderer());
+ addComponent(grid);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Verifies that renderers operating on other data than "
+ + "just Strings also work ";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(13334);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java b/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java
new file mode 100644
index 0000000000..1827f66777
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class CustomRendererTest extends MultiBrowserTest {
+ @Test
+ public void testIntArrayIsRendered() throws Exception {
+ openTestURL();
+
+ GridElement grid = findGrid();
+ assertEquals("1 :: 1 :: 2 :: 3 :: 5 :: 8 :: 13", grid.getCell(0, 0)
+ .getText());
+ }
+
+ private GridElement findGrid() {
+ List<GridElement> elements = $(GridElement.class).all();
+ return elements.get(0);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java
new file mode 100644
index 0000000000..9ebae4587d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java
@@ -0,0 +1,36 @@
+/*
+ * 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.tests.components.grid;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import com.vaadin.ui.components.grid.renderers.AbstractRenderer;
+
+public class IntArrayRenderer extends AbstractRenderer<int[]> {
+ public IntArrayRenderer() {
+ super(int[].class);
+ }
+
+ @Override
+ public Object encode(int[] value) {
+ try {
+ return new JSONArray(value);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java
new file mode 100644
index 0000000000..be358c2738
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java
@@ -0,0 +1,51 @@
+/*
+ * 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.tests.widgetset.client.grid;
+
+import com.vaadin.client.ui.grid.FlyweightCell;
+import com.vaadin.client.ui.grid.Renderer;
+import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector;
+import com.vaadin.shared.ui.Connect;
+
+@Connect(com.vaadin.tests.components.grid.IntArrayRenderer.class)
+public class IntArrayRendererConnector extends AbstractRendererConnector<int[]> {
+
+ public class IntArrayRenderer implements Renderer<int[]> {
+ private static final String JOINER = " :: ";
+
+ @Override
+ public void render(FlyweightCell cell, int[] data) {
+ String text = "";
+ for (int i : data) {
+ text += i + JOINER;
+ }
+ if (!text.isEmpty()) {
+ text = text.substring(0, text.length() - JOINER.length());
+ }
+ cell.getElement().setInnerText(text);
+ }
+ }
+
+ @Override
+ protected IntArrayRenderer createRenderer() {
+ return new IntArrayRenderer();
+ }
+
+ @Override
+ public Class<int[]> getType() {
+ return int[].class;
+ }
+}