summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2014-12-09 21:05:22 +0200
committerVaadin Code Review <review@vaadin.com>2014-12-09 19:25:47 +0000
commitd8c47250a2a8a47fd75e9f48f21aac1ff6aa2170 (patch)
treec9cae6bb22e5cb7cf556dd31cb59befab3531173 /server
parent4157a770fd0df18f6f57b9b9cb017985251f4d0b (diff)
downloadvaadin-framework-d8c47250a2a8a47fd75e9f48f21aac1ff6aa2170.tar.gz
vaadin-framework-d8c47250a2a8a47fd75e9f48f21aac1ff6aa2170.zip
Add Grid.addRow (#13334)
Change-Id: I2c317b920d29ca8a74658ef3b980c6bc2a7622ac
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/data/util/IndexedContainer.java27
-rw-r--r--server/src/com/vaadin/ui/Grid.java77
-rw-r--r--server/tests/src/com/vaadin/data/util/TestIndexedContainer.java35
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java219
4 files changed, 344 insertions, 14 deletions
diff --git a/server/src/com/vaadin/data/util/IndexedContainer.java b/server/src/com/vaadin/data/util/IndexedContainer.java
index f9cc4c482a..b851baf674 100644
--- a/server/src/com/vaadin/data/util/IndexedContainer.java
+++ b/server/src/com/vaadin/data/util/IndexedContainer.java
@@ -242,10 +242,11 @@ public class IndexedContainer extends
return true;
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container#addItem()
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The item ID is generated from a sequence of Integers. The id of the first
+ * added item is 1.
*/
@Override
public Object addItem() {
@@ -363,10 +364,11 @@ public class IndexedContainer extends
new IndexedContainerItem(newItemId), true);
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The item ID is generated from a sequence of Integers. The id of the first
+ * added item is 1.
*/
@Override
public Object addItemAfter(Object previousItemId) {
@@ -392,10 +394,11 @@ public class IndexedContainer extends
newItemId), true);
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Container.Indexed#addItemAt(int)
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The item ID is generated from a sequence of Integers. The id of the first
+ * added item is 1.
*/
@Override
public Object addItemAt(int index) {
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index 1fad4d2304..5f3bea98ca 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.guava.common.collect.Sets.SetView;
@@ -3592,4 +3594,79 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier,
public CellStyleGenerator getCellStyleGenerator() {
return cellStyleGenerator;
}
+
+ /**
+ * Adds a row to the underlying container. The order of the parameters
+ * should match the current visible column order.
+ * <p>
+ * Please note that it's generally only safe to use this method during
+ * initialization. After Grid has been initialized and the visible column
+ * order might have been changed, it's better to instead add items directly
+ * to the underlying container and use {@link Item#getItemProperty(Object)}
+ * to make sure each value is assigned to the intended property.
+ *
+ * @param values
+ * the cell values of the new row, in the same order as the
+ * visible column order, not <code>null</code>.
+ * @return the item id of the new row
+ * @throws IllegalArgumentException
+ * if values is null
+ * @throws IllegalArgumentException
+ * if its length does not match the number of visible columns
+ * @throws IllegalArgumentException
+ * if a parameter value is not an instance of the corresponding
+ * property type
+ * @throws UnsupportedOperationException
+ * if the container does not support adding new items
+ */
+ public Object addRow(Object... values) {
+ if (values == null) {
+ throw new IllegalArgumentException("Values cannot be null");
+ }
+
+ Indexed dataSource = getContainerDataSource();
+ List<String> columnOrder = getState(false).columnOrder;
+
+ if (values.length != columnOrder.size()) {
+ throw new IllegalArgumentException("There are "
+ + columnOrder.size() + " visible columns, but "
+ + values.length + " cell values were provided.");
+ }
+
+ // First verify all parameter types
+ for (int i = 0; i < columnOrder.size(); i++) {
+ Object propertyId = getPropertyIdByColumnId(columnOrder.get(i));
+
+ Class<?> propertyType = dataSource.getType(propertyId);
+ if (values[i] != null && !propertyType.isInstance(values[i])) {
+ throw new IllegalArgumentException("Parameter " + i + "("
+ + values[i] + ") is not an instance of "
+ + propertyType.getCanonicalName());
+ }
+ }
+
+ Object itemId = dataSource.addItem();
+ try {
+ Item item = dataSource.getItem(itemId);
+ for (int i = 0; i < columnOrder.size(); i++) {
+ Object propertyId = getPropertyIdByColumnId(columnOrder.get(i));
+ Property<Object> property = item.getItemProperty(propertyId);
+ property.setValue(values[i]);
+ }
+ } catch (RuntimeException e) {
+ try {
+ dataSource.removeItem(itemId);
+ } catch (Exception e2) {
+ getLogger().log(Level.SEVERE,
+ "Error recovering from exception in addRow", e);
+ }
+ throw e;
+ }
+
+ return itemId;
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(Grid.class.getName());
+ }
}
diff --git a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java
index ddfee103c3..91e222af77 100644
--- a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java
+++ b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java
@@ -2,10 +2,9 @@ package com.vaadin.data.util;
import java.util.List;
-import org.junit.Assert;
-
import org.easymock.Capture;
import org.easymock.EasyMock;
+import org.junit.Assert;
import com.vaadin.data.Container.Indexed.ItemAddEvent;
import com.vaadin.data.Container.Indexed.ItemRemoveEvent;
@@ -277,6 +276,38 @@ public class TestIndexedContainer extends AbstractInMemoryContainerTest {
counter.assertNone();
}
+ public void testItemAdd_idSequence() {
+ IndexedContainer container = new IndexedContainer();
+ Object itemId;
+
+ itemId = container.addItem();
+ assertEquals(Integer.valueOf(1), itemId);
+
+ itemId = container.addItem();
+ assertEquals(Integer.valueOf(2), itemId);
+
+ itemId = container.addItemAfter(null);
+ assertEquals(Integer.valueOf(3), itemId);
+
+ itemId = container.addItemAt(2);
+ assertEquals(Integer.valueOf(4), itemId);
+ }
+
+ public void testItemAddRemove_idSequence() {
+ IndexedContainer container = new IndexedContainer();
+ Object itemId;
+
+ itemId = container.addItem();
+ assertEquals(Integer.valueOf(1), itemId);
+
+ container.removeItem(itemId);
+
+ itemId = container.addItem();
+ assertEquals(
+ "Id sequence should continue from the previous value even if an item is removed",
+ Integer.valueOf(2), itemId);
+ }
+
public void testItemAddedEvent() {
IndexedContainer container = new IndexedContainer();
ItemSetChangeListener addListener = createListenerMockFor(container);
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java
new file mode 100644
index 0000000000..70c73eb516
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java
@@ -0,0 +1,219 @@
+/*
+ * 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.server.component.grid;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.data.util.BeanItemContainer;
+import com.vaadin.data.util.MethodProperty.MethodException;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.Grid;
+
+public class GridAddRowBuiltinContainerTest {
+ Grid grid = new Grid();
+ Container.Indexed container;
+
+ @Before
+ public void setUp() {
+ container = grid.getContainerDataSource();
+
+ grid.addColumn("myColumn");
+ }
+
+ @Test
+ public void testSimpleCase() {
+ Object itemId = grid.addRow("Hello");
+
+ Assert.assertEquals(Integer.valueOf(1), itemId);
+
+ Assert.assertEquals("There should be one item in the container", 1,
+ container.size());
+
+ Assert.assertEquals("Hello",
+ container.getItem(itemId).getItemProperty("myColumn")
+ .getValue());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullParameter() {
+ // cast to Object[] to distinguish from one null varargs value
+ grid.addRow((Object[]) null);
+ }
+
+ @Test
+ public void testNullValue() {
+ // cast to Object to distinguish from a null varargs array
+ Object itemId = grid.addRow((Object) null);
+
+ Assert.assertEquals(null,
+ container.getItem(itemId).getItemProperty("myColumn")
+ .getValue());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddInvalidType() {
+ grid.addRow(Integer.valueOf(5));
+ }
+
+ @Test
+ public void testMultipleProperties() {
+ grid.addColumn("myOther", Integer.class);
+
+ Object itemId = grid.addRow("Hello", Integer.valueOf(3));
+
+ Item item = container.getItem(itemId);
+ Assert.assertEquals("Hello", item.getItemProperty("myColumn")
+ .getValue());
+ Assert.assertEquals(Integer.valueOf(3), item.getItemProperty("myOther")
+ .getValue());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidPropertyAmount() {
+ grid.addRow("Hello", Integer.valueOf(3));
+ }
+
+ @Test
+ public void testRemovedColumn() {
+ grid.addColumn("myOther", Integer.class);
+ grid.removeColumn("myColumn");
+
+ grid.addRow(Integer.valueOf(3));
+
+ Item item = container.getItem(Integer.valueOf(1));
+ Assert.assertEquals("Default value should be used for removed column",
+ "", item.getItemProperty("myColumn").getValue());
+ Assert.assertEquals(Integer.valueOf(3), item.getItemProperty("myOther")
+ .getValue());
+ }
+
+ @Test
+ public void testMultiplePropertiesAfterReorder() {
+ grid.addColumn("myOther", Integer.class);
+
+ grid.setColumnOrder("myOther", "myColumn");
+
+ grid.addRow(Integer.valueOf(3), "Hello");
+
+ Item item = container.getItem(Integer.valueOf(1));
+ Assert.assertEquals("Hello", item.getItemProperty("myColumn")
+ .getValue());
+ Assert.assertEquals(Integer.valueOf(3), item.getItemProperty("myOther")
+ .getValue());
+ }
+
+ @Test
+ public void testInvalidType_NothingAdded() {
+ try {
+ grid.addRow(Integer.valueOf(5));
+
+ // Can't use @Test(expect = Foo.class) since we also want to verify
+ // state after exception was thrown
+ Assert.fail("Adding wrong type should throw ClassCastException");
+ } catch (IllegalArgumentException e) {
+ Assert.assertEquals("No row should have been added", 0,
+ container.size());
+ }
+ }
+
+ @Test
+ public void testUnsupportingContainer() {
+ setContainerRemoveColumns(new BeanItemContainer<Person>(Person.class));
+ try {
+
+ grid.addRow("name");
+
+ // Can't use @Test(expect = Foo.class) since we also want to verify
+ // state after exception was thrown
+ Assert.fail("Adding to BeanItemContainer container should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ Assert.assertEquals("No row should have been added", 0,
+ container.size());
+ }
+ }
+
+ @Test
+ public void testCustomContainer() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class) {
+ @Override
+ public Object addItem() {
+ BeanItem<Person> item = addBean(new Person());
+ return getBeanIdResolver().getIdForBean(item.getBean());
+ }
+ };
+
+ setContainerRemoveColumns(container);
+
+ grid.addRow("name");
+
+ Assert.assertEquals(1, container.size());
+
+ Assert.assertEquals("name", container.getIdByIndex(0).getFirstName());
+ }
+
+ @Test
+ public void testSetterThrowing() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class) {
+ @Override
+ public Object addItem() {
+ BeanItem<Person> item = addBean(new Person() {
+ @Override
+ public void setFirstName(String firstName) {
+ if ("name".equals(firstName)) {
+ throw new RuntimeException(firstName);
+ } else {
+ super.setFirstName(firstName);
+ }
+ }
+ });
+ return getBeanIdResolver().getIdForBean(item.getBean());
+ }
+ };
+
+ setContainerRemoveColumns(container);
+
+ try {
+
+ grid.addRow("name");
+
+ // Can't use @Test(expect = Foo.class) since we also want to verify
+ // state after exception was thrown
+ Assert.fail("Adding row should throw MethodException");
+ } catch (MethodException e) {
+ Assert.assertEquals("Got the wrong exception", "name", e.getCause()
+ .getMessage());
+
+ Assert.assertEquals("There should be no rows in the container", 0,
+ container.size());
+ }
+ }
+
+ private void setContainerRemoveColumns(BeanItemContainer<Person> container) {
+ // Remove predefined column so we can change container
+ grid.removeAllColumns();
+ grid.setContainerDataSource(container);
+ grid.removeAllColumns();
+ grid.addColumn("firstName");
+ }
+
+}