summaryrefslogtreecommitdiffstats
path: root/compatibility-server/src/test
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2016-08-18 18:04:59 +0300
committerArtur Signell <artur@vaadin.com>2016-08-20 00:08:44 +0300
commit6e0f2efe996cfd3b38c960e04cbced0a91215cf0 (patch)
tree9eafac7107b3d34d8d1e9bc7631a1debad4fd720 /compatibility-server/src/test
parent016a2ceb86f771a3902ace98d9fe56351c0efdf2 (diff)
downloadvaadin-framework-6e0f2efe996cfd3b38c960e04cbced0a91215cf0.tar.gz
vaadin-framework-6e0f2efe996cfd3b38c960e04cbced0a91215cf0.zip
Move FieldGroup and Vaadin 7 Grid to compatibility package
Change-Id: I9aaef478e0b67462641239802b924b8461cb9225
Diffstat (limited to 'compatibility-server/src/test')
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java70
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java125
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java97
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java33
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java96
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java77
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java866
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java289
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java6
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java516
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java150
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java166
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java997
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java389
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java26
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java107
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java59
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java222
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java16
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java596
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java318
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java33
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java286
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java533
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java150
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java351
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java102
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java120
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java84
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java432
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java35
-rw-r--r--compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java117
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java163
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java172
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java85
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java149
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java51
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java53
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java219
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java59
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java134
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java413
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java103
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java159
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java296
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java41
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java377
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java44
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java132
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java171
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java153
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java62
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java101
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java84
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java159
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java356
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java124
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java50
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java205
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java85
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java268
-rw-r--r--compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java129
-rw-r--r--compatibility-server/src/test/java/com/vaadin/ui/TableTest.java78
63 files changed, 12139 insertions, 0 deletions
diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java
new file mode 100644
index 0000000000..3333cd7744
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 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.fieldgroup;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BeanFieldGroupTest {
+
+ class Main {
+ private String mainField;
+
+ public String getMainField() {
+ return mainField;
+ }
+
+ public void setMainField(String mainField) {
+ this.mainField = mainField;
+ }
+
+ }
+
+ class Sub1 extends Main {
+ private Integer sub1Field;
+
+ public Integer getSub1Field() {
+ return sub1Field;
+ }
+
+ public void setSub1Field(Integer sub1Field) {
+ this.sub1Field = sub1Field;
+ }
+
+ }
+
+ class Sub2 extends Sub1 {
+ private boolean sub2field;
+
+ public boolean isSub2field() {
+ return sub2field;
+ }
+
+ public void setSub2field(boolean sub2field) {
+ this.sub2field = sub2field;
+ }
+
+ }
+
+ @Test
+ public void propertyTypeWithoutItem() {
+ BeanFieldGroup<Sub2> s = new BeanFieldGroup<BeanFieldGroupTest.Sub2>(
+ Sub2.class);
+ Assert.assertEquals(boolean.class, s.getPropertyType("sub2field"));
+ Assert.assertEquals(Integer.class, s.getPropertyType("sub1Field"));
+ Assert.assertEquals(String.class, s.getPropertyType("mainField"));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java
new file mode 100644
index 0000000000..93aa1350b0
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2000-2016 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.fieldgroup;
+
+import java.lang.reflect.Constructor;
+import java.util.Date;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.DefaultFieldGroupFieldFactory;
+import com.vaadin.ui.AbstractSelect;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.ListSelect;
+import com.vaadin.v7.ui.LegacyDateField;
+import com.vaadin.v7.ui.LegacyField;
+import com.vaadin.v7.ui.LegacyInlineDateField;
+import com.vaadin.v7.ui.LegacyPopupDateField;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class DefaultFieldGroupFieldFactoryTest {
+
+ private DefaultFieldGroupFieldFactory fieldFactory;
+
+ @Before
+ public void setupFieldFactory() {
+ fieldFactory = DefaultFieldGroupFieldFactory.get();
+ }
+
+ @Test
+ public void noPublicConstructor() {
+ Class<DefaultFieldGroupFieldFactory> clazz = DefaultFieldGroupFieldFactory.class;
+ Constructor<?>[] constructors = clazz.getConstructors();
+ Assert.assertEquals(
+ "DefaultFieldGroupFieldFactory contains public constructors", 0,
+ constructors.length);
+ }
+
+ @Test
+ public void testSameInstance() {
+ DefaultFieldGroupFieldFactory factory1 = DefaultFieldGroupFieldFactory
+ .get();
+ DefaultFieldGroupFieldFactory factory2 = DefaultFieldGroupFieldFactory
+ .get();
+ Assert.assertTrue(
+ "DefaultFieldGroupFieldFactory.get() method returns different instances",
+ factory1 == factory2);
+ Assert.assertNotNull(
+ "DefaultFieldGroupFieldFactory.get() method returns null",
+ factory1);
+ }
+
+ @Test
+ public void testDateGenerationForPopupDateField() {
+ LegacyField f = fieldFactory.createField(Date.class,
+ LegacyDateField.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(LegacyPopupDateField.class, f.getClass());
+ }
+
+ @Test
+ public void testDateGenerationForInlineDateField() {
+ LegacyField f = fieldFactory.createField(Date.class,
+ LegacyInlineDateField.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(LegacyInlineDateField.class, f.getClass());
+ }
+
+ @Test
+ public void testDateGenerationForTextField() {
+ LegacyField f = fieldFactory.createField(Date.class,
+ LegacyTextField.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(LegacyTextField.class, f.getClass());
+ }
+
+ @Test
+ public void testDateGenerationForField() {
+ LegacyField f = fieldFactory.createField(Date.class, LegacyField.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(LegacyPopupDateField.class, f.getClass());
+ }
+
+ public enum SomeEnum {
+ FOO, BAR;
+ }
+
+ @Test
+ public void testEnumComboBox() {
+ LegacyField f = fieldFactory.createField(SomeEnum.class,
+ ComboBox.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(ComboBox.class, f.getClass());
+ }
+
+ @Test
+ public void testEnumAnySelect() {
+ LegacyField f = fieldFactory.createField(SomeEnum.class,
+ AbstractSelect.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(ListSelect.class, f.getClass());
+ }
+
+ @Test
+ public void testEnumAnyField() {
+ LegacyField f = fieldFactory.createField(SomeEnum.class,
+ LegacyField.class);
+ Assert.assertNotNull(f);
+ Assert.assertEquals(ListSelect.class, f.getClass());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java
new file mode 100644
index 0000000000..e270211abf
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2016 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.fieldgroup;
+
+import java.util.Date;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.v7.ui.LegacyField;
+import com.vaadin.v7.ui.LegacyPopupDateField;
+
+public class FieldGroupDateTest {
+
+ private FieldGroup fieldGroup;
+
+ public class TestBean {
+ private Date javaDate;
+ private java.sql.Date sqlDate;
+
+ public TestBean(Date javaDate, java.sql.Date sqlDate) {
+ super();
+ this.javaDate = javaDate;
+ this.sqlDate = sqlDate;
+ }
+
+ public java.sql.Date getSqlDate() {
+ return sqlDate;
+ }
+
+ public void setSqlDate(java.sql.Date sqlDate) {
+ this.sqlDate = sqlDate;
+ }
+
+ public Date getJavaDate() {
+ return javaDate;
+ }
+
+ public void setJavaDate(Date date) {
+ javaDate = date;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Before
+ public void setup() {
+ fieldGroup = new FieldGroup();
+ fieldGroup.setItemDataSource(new BeanItem<TestBean>(new TestBean(
+ new Date(2010, 5, 7), new java.sql.Date(2011, 6, 8))));
+ }
+
+ @Test
+ public void testBuildAndBindDate() {
+ LegacyField f = fieldGroup.buildAndBind("javaDate");
+ Assert.assertNotNull(f);
+ Assert.assertEquals(LegacyPopupDateField.class, f.getClass());
+ }
+
+ @Test
+ public void testBuildAndBindSqlDate() {
+ LegacyField f = fieldGroup.buildAndBind("sqlDate");
+ Assert.assertNotNull(f);
+ Assert.assertEquals(LegacyPopupDateField.class, f.getClass());
+ }
+
+ @Test
+ public void clearFields() {
+ LegacyPopupDateField sqlDate = new LegacyPopupDateField();
+ LegacyPopupDateField javaDate = new LegacyPopupDateField();
+ fieldGroup.bind(sqlDate, "sqlDate");
+ fieldGroup.bind(javaDate, "javaDate");
+
+ Assert.assertEquals(new Date(2010, 5, 7), javaDate.getValue());
+ Assert.assertEquals(new Date(2011, 6, 8), sqlDate.getValue());
+
+ fieldGroup.clear();
+ Assert.assertEquals(null, javaDate.getValue());
+ Assert.assertEquals(null, sqlDate.getValue());
+
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java
new file mode 100644
index 0000000000..4622f0960e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2016 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.fieldgroup;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.v7.ui.LegacyPopupDateField;
+
+public class FieldGroupExceptionTest {
+
+ @Test(expected = CommitException.class)
+ public void testUnboundCommitException() throws CommitException {
+ FieldGroup fieldGroup = new FieldGroup();
+ LegacyPopupDateField dateField = new LegacyPopupDateField();
+ fieldGroup.bind(dateField, "date");
+ fieldGroup.commit();
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java
new file mode 100644
index 0000000000..c0039fc4fb
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java
@@ -0,0 +1,96 @@
+package com.vaadin.data.fieldgroup;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Property;
+import com.vaadin.data.Property.Transactional;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.data.util.TransactionalPropertyWrapper;
+import com.vaadin.v7.ui.LegacyField;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class FieldGroupTest {
+
+ private FieldGroup sut;
+ private LegacyField field;
+
+ @Before
+ public void setup() {
+ sut = new FieldGroup();
+ field = mock(LegacyField.class);
+ }
+
+ @Test
+ public void fieldIsBound() {
+ sut.bind(field, "foobar");
+
+ assertThat(sut.getField("foobar"), is(field));
+ }
+
+ @Test(expected = FieldGroup.BindException.class)
+ public void cannotBindToAlreadyBoundProperty() {
+ sut.bind(field, "foobar");
+ sut.bind(mock(LegacyField.class), "foobar");
+ }
+
+ @Test(expected = FieldGroup.BindException.class)
+ public void cannotBindNullField() {
+ sut.bind(null, "foobar");
+ }
+
+ public void canUnbindWithoutItem() {
+ sut.bind(field, "foobar");
+
+ sut.unbind(field);
+ assertThat(sut.getField("foobar"), is(nullValue()));
+ }
+
+ @Test
+ public void wrapInTransactionalProperty_provideCustomImpl_customTransactionalWrapperIsUsed() {
+ Bean bean = new Bean();
+ FieldGroup group = new FieldGroup() {
+ @Override
+ protected <T> Transactional<T> wrapInTransactionalProperty(
+ Property<T> itemProperty) {
+ return new TransactionalPropertyImpl(itemProperty);
+ }
+ };
+ group.setItemDataSource(new BeanItem<Bean>(bean));
+ LegacyTextField field = new LegacyTextField();
+ group.bind(field, "name");
+
+ Property propertyDataSource = field.getPropertyDataSource();
+ Assert.assertTrue(
+ "Custom implementation of transactional property "
+ + "has not been used",
+ propertyDataSource instanceof TransactionalPropertyImpl);
+ }
+
+ public static class TransactionalPropertyImpl<T>
+ extends TransactionalPropertyWrapper<T> {
+
+ public TransactionalPropertyImpl(Property<T> wrappedProperty) {
+ super(wrappedProperty);
+ }
+
+ }
+
+ public static class Bean {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java
new file mode 100644
index 0000000000..4a9e4f9891
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java
@@ -0,0 +1,77 @@
+package com.vaadin.data.util;
+
+/**
+ * Automated test for {@link AbstractBeanContainer}.
+ *
+ * Only a limited subset of the functionality is tested here, the rest in tests
+ * of subclasses including {@link BeanItemContainer} and {@link BeanContainer}.
+ */
+public abstract class AbstractBeanContainerTestBase
+ extends AbstractInMemoryContainerTestBase {
+
+ public static class Person {
+ private String name;
+
+ public Person(String name) {
+ setName(name);
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public static class ClassName {
+ // field names match constants in parent test class
+ private String fullyQualifiedName;
+ private String simpleName;
+ private String reverseFullyQualifiedName;
+ private Integer idNumber;
+
+ public ClassName(String fullyQualifiedName, Integer idNumber) {
+ this.fullyQualifiedName = fullyQualifiedName;
+ simpleName = AbstractContainerTestBase
+ .getSimpleName(fullyQualifiedName);
+ reverseFullyQualifiedName = reverse(fullyQualifiedName);
+ this.idNumber = idNumber;
+ }
+
+ public String getFullyQualifiedName() {
+ return fullyQualifiedName;
+ }
+
+ public void setFullyQualifiedName(String fullyQualifiedName) {
+ this.fullyQualifiedName = fullyQualifiedName;
+ }
+
+ public String getSimpleName() {
+ return simpleName;
+ }
+
+ public void setSimpleName(String simpleName) {
+ this.simpleName = simpleName;
+ }
+
+ public String getReverseFullyQualifiedName() {
+ return reverseFullyQualifiedName;
+ }
+
+ public void setReverseFullyQualifiedName(
+ String reverseFullyQualifiedName) {
+ this.reverseFullyQualifiedName = reverseFullyQualifiedName;
+ }
+
+ public Integer getIdNumber() {
+ return idNumber;
+ }
+
+ public void setIdNumber(Integer idNumber) {
+ this.idNumber = idNumber;
+ }
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java
new file mode 100644
index 0000000000..955b609735
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java
@@ -0,0 +1,866 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Assert;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Filterable;
+import com.vaadin.data.Container.ItemSetChangeEvent;
+import com.vaadin.data.Container.ItemSetChangeListener;
+import com.vaadin.data.Container.Ordered;
+import com.vaadin.data.Container.Sortable;
+import com.vaadin.data.Item;
+import com.vaadin.data.util.filter.SimpleStringFilter;
+
+public abstract class AbstractContainerTestBase {
+
+ /**
+ * Helper class for testing e.g. listeners expecting events to be fired.
+ */
+ protected abstract static class AbstractEventCounter {
+ private int eventCount = 0;
+ private int lastAssertedEventCount = 0;
+
+ /**
+ * Increment the event count. To be called by subclasses e.g. from a
+ * listener method.
+ */
+ protected void increment() {
+ ++eventCount;
+ }
+
+ /**
+ * Check that no one event has occurred since the previous assert call.
+ */
+ public void assertNone() {
+ Assert.assertEquals(lastAssertedEventCount, eventCount);
+ }
+
+ /**
+ * Check that exactly one event has occurred since the previous assert
+ * call.
+ */
+ public void assertOnce() {
+ Assert.assertEquals(++lastAssertedEventCount, eventCount);
+ }
+
+ /**
+ * Reset the counter and the expected count.
+ */
+ public void reset() {
+ eventCount = 0;
+ lastAssertedEventCount = 0;
+ }
+ }
+
+ /**
+ * Test class for counting item set change events and verifying they have
+ * been received.
+ */
+ protected static class ItemSetChangeCounter extends AbstractEventCounter
+ implements ItemSetChangeListener {
+
+ @Override
+ public void containerItemSetChange(ItemSetChangeEvent event) {
+ increment();
+ }
+
+ }
+
+ // #6043: for items that have been filtered out, Container interface does
+ // not specify what to return from getItem() and getContainerProperty(), so
+ // need checkGetItemNull parameter for the test to be usable for most
+ // current containers
+ protected void validateContainer(Container container,
+ Object expectedFirstItemId, Object expectedLastItemId,
+ Object itemIdInSet, Object itemIdNotInSet, boolean checkGetItemNull,
+ int expectedSize) {
+ Container.Indexed indexed = null;
+ if (container instanceof Container.Indexed) {
+ indexed = (Container.Indexed) container;
+ }
+
+ List<Object> itemIdList = new ArrayList<Object>(container.getItemIds());
+
+ // size()
+ assertEquals(expectedSize, container.size());
+ assertEquals(expectedSize, itemIdList.size());
+
+ // first item, last item
+ Object first = itemIdList.get(0);
+ Object last = itemIdList.get(itemIdList.size() - 1);
+
+ assertEquals(expectedFirstItemId, first);
+ assertEquals(expectedLastItemId, last);
+
+ // containsId
+ assertFalse(container.containsId(itemIdNotInSet));
+ assertTrue(container.containsId(itemIdInSet));
+
+ // getItem
+ if (checkGetItemNull) {
+ assertNull(container.getItem(itemIdNotInSet));
+ }
+ assertNotNull(container.getItem(itemIdInSet));
+
+ // getContainerProperty
+ for (Object propId : container.getContainerPropertyIds()) {
+ if (checkGetItemNull) {
+ assertNull(
+ container.getContainerProperty(itemIdNotInSet, propId));
+ }
+ assertNotNull(container.getContainerProperty(itemIdInSet, propId));
+ }
+
+ if (indexed != null) {
+ // firstItemId
+ assertEquals(first, indexed.firstItemId());
+
+ // lastItemId
+ assertEquals(last, indexed.lastItemId());
+
+ // nextItemId
+ assertEquals(itemIdList.get(1), indexed.nextItemId(first));
+
+ // prevItemId
+ assertEquals(itemIdList.get(itemIdList.size() - 2),
+ indexed.prevItemId(last));
+
+ // isFirstId
+ assertTrue(indexed.isFirstId(first));
+ assertFalse(indexed.isFirstId(last));
+
+ // isLastId
+ assertTrue(indexed.isLastId(last));
+ assertFalse(indexed.isLastId(first));
+
+ // indexOfId
+ assertEquals(0, indexed.indexOfId(first));
+ assertEquals(expectedSize - 1, indexed.indexOfId(last));
+
+ // getIdByIndex
+ assertEquals(indexed.getIdByIndex(0), first);
+ assertEquals(indexed.getIdByIndex(expectedSize - 1), last);
+
+ }
+
+ // getItemProperty
+ Assert.assertNull(
+ container.getItem(itemIdInSet).getItemProperty("notinset"));
+
+ }
+
+ protected static final Object FULLY_QUALIFIED_NAME = "fullyQualifiedName";
+ protected static final Object SIMPLE_NAME = "simpleName";
+ protected static final Object REVERSE_FULLY_QUALIFIED_NAME = "reverseFullyQualifiedName";
+ protected static final Object ID_NUMBER = "idNumber";
+
+ protected void testBasicContainerOperations(Container container) {
+ initializeContainer(container);
+
+ // Basic container
+ validateContainer(container, sampleData[0],
+ sampleData[sampleData.length - 1], sampleData[10], "abc", true,
+ sampleData.length);
+
+ validateRemovingItems(container);
+ validateAddItem(container);
+ if (container instanceof Container.Indexed) {
+ validateAddItemAt((Container.Indexed) container);
+ }
+ if (container instanceof Container.Ordered) {
+ validateAddItemAfter((Container.Ordered) container);
+ }
+
+ }
+
+ protected void validateRemovingItems(Container container) {
+ int sizeBeforeRemoving = container.size();
+
+ List<Object> itemIdList = new ArrayList<Object>(container.getItemIds());
+ // There should be at least four items in the list
+ Object first = itemIdList.get(0);
+ Object middle = itemIdList.get(2);
+ Object last = itemIdList.get(itemIdList.size() - 1);
+
+ container.removeItem(first);
+ container.removeItem(middle); // Middle now that first has been removed
+ container.removeItem(last);
+
+ assertEquals(sizeBeforeRemoving - 3, container.size());
+
+ container.removeAllItems();
+
+ assertEquals(0, container.size());
+ }
+
+ protected void validateAddItem(Container container) {
+ try {
+ container.removeAllItems();
+
+ Object id = container.addItem();
+ Assert.assertTrue(container.containsId(id));
+ Assert.assertNotNull(container.getItem(id));
+
+ Item item = container.addItem("foo");
+ Assert.assertNotNull(item);
+ Assert.assertTrue(container.containsId("foo"));
+ Assert.assertEquals(item, container.getItem("foo"));
+
+ // Add again
+ Item item2 = container.addItem("foo");
+ Assert.assertNull(item2);
+
+ // Null is not a valid itemId
+ Assert.assertNull(container.addItem(null));
+ } catch (UnsupportedOperationException e) {
+ // Ignore contains which do not support addItem*
+ }
+ }
+
+ protected void validateAddItemAt(Container.Indexed container) {
+ try {
+ container.removeAllItems();
+
+ Object id = container.addItemAt(0);
+ Assert.assertTrue(container.containsId(id));
+ Assert.assertEquals(id, container.getIdByIndex(0));
+ Assert.assertNotNull(container.getItem(id));
+
+ Item item = container.addItemAt(0, "foo");
+ Assert.assertNotNull(item);
+ Assert.assertTrue(container.containsId("foo"));
+ Assert.assertEquals(item, container.getItem("foo"));
+ Assert.assertEquals("foo", container.getIdByIndex(0));
+
+ Item itemAtEnd = container.addItemAt(2, "atend");
+ Assert.assertNotNull(itemAtEnd);
+ Assert.assertTrue(container.containsId("atend"));
+ Assert.assertEquals(itemAtEnd, container.getItem("atend"));
+ Assert.assertEquals("atend", container.getIdByIndex(2));
+
+ // Add again
+ Item item2 = container.addItemAt(0, "foo");
+ Assert.assertNull(item2);
+ } catch (UnsupportedOperationException e) {
+ // Ignore contains which do not support addItem*
+ }
+ }
+
+ protected void validateAddItemAfter(Container.Ordered container) {
+ if (container instanceof AbstractBeanContainer) {
+ // Doesn't work as bean container requires beans
+ return;
+ }
+
+ try {
+ container.removeAllItems();
+
+ Assert.assertNotNull(container.addItem(0));
+
+ Item item = container.addItemAfter(null, "foo");
+ Assert.assertNotNull(item);
+ Assert.assertTrue(container.containsId("foo"));
+ Assert.assertEquals(item, container.getItem("foo"));
+ Assert.assertEquals("foo",
+ container.getItemIds().iterator().next());
+
+ Item itemAtEnd = container.addItemAfter(0, "atend");
+ Assert.assertNotNull(itemAtEnd);
+ Assert.assertTrue(container.containsId("atend"));
+ Assert.assertEquals(itemAtEnd, container.getItem("atend"));
+ Iterator<?> i = container.getItemIds().iterator();
+ i.next();
+ i.next();
+ Assert.assertEquals("atend", i.next());
+
+ // Add again
+ Assert.assertNull(container.addItemAfter(null, "foo"));
+ Assert.assertNull(container.addItemAfter("atend", "foo"));
+ Assert.assertNull(container.addItemAfter("nonexistant", "123123"));
+ } catch (UnsupportedOperationException e) {
+ // Ignore contains which do not support addItem*
+ }
+ }
+
+ protected void testContainerOrdered(Container.Ordered container) {
+ // addItem with empty container
+ Object id = container.addItem();
+ assertOrderedContents(container, id);
+ Item item = container.getItem(id);
+ assertNotNull(item);
+
+ // addItemAfter with empty container
+ container.removeAllItems();
+ assertOrderedContents(container);
+ id = container.addItemAfter(null);
+ assertOrderedContents(container, id);
+ item = container.getItem(id);
+ assertNotNull(item);
+
+ // Add a new item before the first
+ // addItemAfter
+ Object newFirstId = container.addItemAfter(null);
+ assertOrderedContents(container, newFirstId, id);
+
+ // addItemAfter(Object)
+ Object newSecondItemId = container.addItemAfter(newFirstId);
+ // order is now: newFirstId, newSecondItemId, id
+ assertOrderedContents(container, newFirstId, newSecondItemId, id);
+
+ // addItemAfter(Object,Object)
+ String fourthId = "id of the fourth item";
+ Item fourth = container.addItemAfter(newFirstId, fourthId);
+ // order is now: newFirstId, fourthId, newSecondItemId, id
+ assertNotNull(fourth);
+ assertEquals(fourth, container.getItem(fourthId));
+ assertOrderedContents(container, newFirstId, fourthId, newSecondItemId,
+ id);
+
+ // addItemAfter(Object,Object)
+ Object fifthId = new Object();
+ Item fifth = container.addItemAfter(null, fifthId);
+ // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id
+ assertNotNull(fifth);
+ assertEquals(fifth, container.getItem(fifthId));
+ assertOrderedContents(container, fifthId, newFirstId, fourthId,
+ newSecondItemId, id);
+
+ // addItemAfter(Object,Object)
+ Object sixthId = new Object();
+ Item sixth = container.addItemAfter(id, sixthId);
+ // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id,
+ // sixthId
+ assertNotNull(sixth);
+ assertEquals(sixth, container.getItem(sixthId));
+ assertOrderedContents(container, fifthId, newFirstId, fourthId,
+ newSecondItemId, id, sixthId);
+
+ // Test order after removing first item 'fifthId'
+ container.removeItem(fifthId);
+ // order is now: newFirstId, fourthId, newSecondItemId, id, sixthId
+ assertOrderedContents(container, newFirstId, fourthId, newSecondItemId,
+ id, sixthId);
+
+ // Test order after removing last item 'sixthId'
+ container.removeItem(sixthId);
+ // order is now: newFirstId, fourthId, newSecondItemId, id
+ assertOrderedContents(container, newFirstId, fourthId, newSecondItemId,
+ id);
+
+ // Test order after removing item from the middle 'fourthId'
+ container.removeItem(fourthId);
+ // order is now: newFirstId, newSecondItemId, id
+ assertOrderedContents(container, newFirstId, newSecondItemId, id);
+
+ // Delete remaining items
+ container.removeItem(newFirstId);
+ container.removeItem(newSecondItemId);
+ container.removeItem(id);
+ assertOrderedContents(container);
+
+ Object finalItem = container.addItem();
+ assertOrderedContents(container, finalItem);
+ }
+
+ private void assertOrderedContents(Ordered container, Object... ids) {
+ assertEquals(ids.length, container.size());
+ for (int i = 0; i < ids.length - 1; i++) {
+ assertNotNull("The item id should not be null", ids[i]);
+ }
+ if (ids.length == 0) {
+ assertNull("The first id is wrong", container.firstItemId());
+ assertNull("The last id is wrong", container.lastItemId());
+ return;
+ }
+
+ assertEquals("The first id is wrong", ids[0], container.firstItemId());
+ assertEquals("The last id is wrong", ids[ids.length - 1],
+ container.lastItemId());
+
+ // isFirstId & isLastId
+ assertTrue(container.isFirstId(container.firstItemId()));
+ assertTrue(container.isLastId(container.lastItemId()));
+
+ // nextId
+ Object ref = container.firstItemId();
+ for (int i = 1; i < ids.length; i++) {
+ Object next = container.nextItemId(ref);
+ assertEquals("The id after " + ref + " is wrong", ids[i], next);
+ ref = next;
+ }
+ assertNull("The last id should not have a next id",
+ container.nextItemId(ids[ids.length - 1]));
+ assertNull(container.nextItemId("not-in-container"));
+
+ // prevId
+ ref = container.lastItemId();
+ for (int i = ids.length - 2; i >= 0; i--) {
+ Object prev = container.prevItemId(ref);
+ assertEquals("The id before " + ref + " is wrong", ids[i], prev);
+ ref = prev;
+ }
+ assertNull("The first id should not have a prev id",
+ container.prevItemId(ids[0]));
+ assertNull(container.prevItemId("not-in-container"));
+
+ }
+
+ protected void testContainerIndexed(Container.Indexed container,
+ Object itemId, int itemPosition, boolean testAddEmptyItemAt,
+ Object newItemId, boolean testAddItemAtWithId) {
+ initializeContainer(container);
+
+ // indexOfId
+ Assert.assertEquals(itemPosition, container.indexOfId(itemId));
+
+ // getIdByIndex
+ Assert.assertEquals(itemId, container.getIdByIndex(itemPosition));
+
+ // addItemAt
+ if (testAddEmptyItemAt) {
+ Object addedId = container.addItemAt(itemPosition);
+ Assert.assertEquals(itemPosition, container.indexOfId(addedId));
+ Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId));
+ Assert.assertEquals(addedId, container.getIdByIndex(itemPosition));
+ Assert.assertEquals(itemId,
+ container.getIdByIndex(itemPosition + 1));
+
+ Object newFirstId = container.addItemAt(0);
+ Assert.assertEquals(0, container.indexOfId(newFirstId));
+ Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId));
+ Assert.assertEquals(newFirstId, container.firstItemId());
+ Assert.assertEquals(newFirstId, container.getIdByIndex(0));
+ Assert.assertEquals(itemId,
+ container.getIdByIndex(itemPosition + 2));
+
+ Object newLastId = container.addItemAt(container.size());
+ Assert.assertEquals(container.size() - 1,
+ container.indexOfId(newLastId));
+ Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId));
+ Assert.assertEquals(newLastId, container.lastItemId());
+ Assert.assertEquals(newLastId,
+ container.getIdByIndex(container.size() - 1));
+ Assert.assertEquals(itemId,
+ container.getIdByIndex(itemPosition + 2));
+
+ Assert.assertTrue(container.removeItem(addedId));
+ Assert.assertTrue(container.removeItem(newFirstId));
+ Assert.assertTrue(container.removeItem(newLastId));
+
+ Assert.assertFalse(
+ "Removing non-existing item should indicate failure",
+ container.removeItem(addedId));
+ }
+
+ // addItemAt
+ if (testAddItemAtWithId) {
+ container.addItemAt(itemPosition, newItemId);
+ Assert.assertEquals(itemPosition, container.indexOfId(newItemId));
+ Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId));
+ Assert.assertEquals(newItemId,
+ container.getIdByIndex(itemPosition));
+ Assert.assertEquals(itemId,
+ container.getIdByIndex(itemPosition + 1));
+ Assert.assertTrue(container.removeItem(newItemId));
+ Assert.assertFalse(container.containsId(newItemId));
+
+ container.addItemAt(0, newItemId);
+ Assert.assertEquals(0, container.indexOfId(newItemId));
+ Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId));
+ Assert.assertEquals(newItemId, container.firstItemId());
+ Assert.assertEquals(newItemId, container.getIdByIndex(0));
+ Assert.assertEquals(itemId,
+ container.getIdByIndex(itemPosition + 1));
+ Assert.assertTrue(container.removeItem(newItemId));
+ Assert.assertFalse(container.containsId(newItemId));
+
+ container.addItemAt(container.size(), newItemId);
+ Assert.assertEquals(container.size() - 1,
+ container.indexOfId(newItemId));
+ Assert.assertEquals(itemPosition, container.indexOfId(itemId));
+ Assert.assertEquals(newItemId, container.lastItemId());
+ Assert.assertEquals(newItemId,
+ container.getIdByIndex(container.size() - 1));
+ Assert.assertEquals(itemId, container.getIdByIndex(itemPosition));
+ Assert.assertTrue(container.removeItem(newItemId));
+ Assert.assertFalse(container.containsId(newItemId));
+ }
+ }
+
+ protected void testContainerFiltering(Container.Filterable container) {
+ initializeContainer(container);
+
+ // Filter by "contains ab"
+ SimpleStringFilter filter1 = new SimpleStringFilter(
+ FULLY_QUALIFIED_NAME, "ab", false, false);
+ container.addContainerFilter(filter1);
+
+ assertTrue(container.getContainerFilters().size() == 1);
+ assertEquals(filter1,
+ container.getContainerFilters().iterator().next());
+
+ validateContainer(container, "com.vaadin.data.BufferedValidatable",
+ "com.vaadin.ui.TabSheet",
+ "com.vaadin.terminal.gwt.client.Focusable",
+ "com.vaadin.data.Buffered", isFilteredOutItemNull(), 20);
+
+ // Filter by "contains da" (reversed as ad here)
+ container.removeAllContainerFilters();
+
+ assertTrue(container.getContainerFilters().isEmpty());
+
+ SimpleStringFilter filter2 = new SimpleStringFilter(
+ REVERSE_FULLY_QUALIFIED_NAME, "ad", false, false);
+ container.addContainerFilter(filter2);
+
+ assertTrue(container.getContainerFilters().size() == 1);
+ assertEquals(filter2,
+ container.getContainerFilters().iterator().next());
+
+ validateContainer(container, "com.vaadin.data.Buffered",
+ "com.vaadin.server.ComponentSizeValidator",
+ "com.vaadin.data.util.IndexedContainer",
+ "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility",
+ isFilteredOutItemNull(), 37);
+ }
+
+ /**
+ * Override in subclasses to return false if the container getItem() method
+ * returns a non-null value for an item that has been filtered out.
+ *
+ * @return
+ */
+ protected boolean isFilteredOutItemNull() {
+ return true;
+ }
+
+ protected void testContainerSortingAndFiltering(
+ Container.Sortable sortable) {
+ Filterable filterable = (Filterable) sortable;
+
+ initializeContainer(sortable);
+
+ // Filter by "contains ab"
+ filterable.addContainerFilter(new SimpleStringFilter(
+ FULLY_QUALIFIED_NAME, "ab", false, false));
+
+ // Must be able to sort based on PROP1 for this test
+ assertTrue(sortable.getSortableContainerPropertyIds()
+ .contains(FULLY_QUALIFIED_NAME));
+
+ sortable.sort(new Object[] { FULLY_QUALIFIED_NAME },
+ new boolean[] { true });
+
+ validateContainer(sortable, "com.vaadin.data.BufferedValidatable",
+ "com.vaadin.ui.TableFieldFactory",
+ "com.vaadin.ui.TableFieldFactory",
+ "com.vaadin.data.util.BeanItem", isFilteredOutItemNull(), 20);
+ }
+
+ protected void testContainerSorting(Container.Filterable container) {
+ Container.Sortable sortable = (Sortable) container;
+
+ initializeContainer(container);
+
+ // Must be able to sort based on PROP1 for this test
+ assertTrue(sortable.getSortableContainerPropertyIds()
+ .contains(FULLY_QUALIFIED_NAME));
+ assertTrue(sortable.getSortableContainerPropertyIds()
+ .contains(REVERSE_FULLY_QUALIFIED_NAME));
+
+ sortable.sort(new Object[] { FULLY_QUALIFIED_NAME },
+ new boolean[] { true });
+
+ validateContainer(container, "com.vaadin.Application",
+ "org.vaadin.test.LastClass",
+ "com.vaadin.server.ApplicationResource", "blah", true,
+ sampleData.length);
+
+ sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME },
+ new boolean[] { true });
+
+ validateContainer(container, "com.vaadin.server.ApplicationPortlet2",
+ "com.vaadin.data.util.ObjectProperty",
+ "com.vaadin.ui.BaseFieldFactory", "blah", true,
+ sampleData.length);
+
+ }
+
+ protected void initializeContainer(Container container) {
+ Assert.assertTrue(container.removeAllItems());
+ Object[] propertyIds = container.getContainerPropertyIds().toArray();
+ for (Object propertyId : propertyIds) {
+ container.removeContainerProperty(propertyId);
+ }
+
+ container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, "");
+ container.addContainerProperty(SIMPLE_NAME, String.class, "");
+ container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME,
+ String.class, null);
+ container.addContainerProperty(ID_NUMBER, Integer.class, null);
+
+ for (int i = 0; i < sampleData.length; i++) {
+ String id = sampleData[i];
+ Item item = container.addItem(id);
+
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]);
+ item.getItemProperty(SIMPLE_NAME)
+ .setValue(getSimpleName(sampleData[i]));
+ item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME)
+ .setValue(reverse(sampleData[i]));
+ item.getItemProperty(ID_NUMBER).setValue(i);
+ }
+ }
+
+ protected static String getSimpleName(String name) {
+ if (name.contains(".")) {
+ return name.substring(name.lastIndexOf('.') + 1);
+ } else {
+ return name;
+ }
+ }
+
+ protected static String reverse(String string) {
+ return new StringBuilder(string).reverse().toString();
+ }
+
+ protected final String[] sampleData = {
+ "com.vaadin.annotations.AutoGenerated", "com.vaadin.Application",
+ "com.vaadin.data.Buffered", "com.vaadin.data.BufferedValidatable",
+ "com.vaadin.data.Container", "com.vaadin.data.Item",
+ "com.vaadin.data.Property", "com.vaadin.data.util.BeanItem",
+ "com.vaadin.data.util.BeanItemContainer",
+ "com.vaadin.data.util.ContainerHierarchicalWrapper",
+ "com.vaadin.data.util.ContainerOrderedWrapper",
+ "com.vaadin.data.util.DefaultItemSorter",
+ "com.vaadin.data.util.FilesystemContainer",
+ "com.vaadin.data.util.Filter",
+ "com.vaadin.data.util.HierarchicalContainer",
+ "com.vaadin.data.util.IndexedContainer",
+ "com.vaadin.data.util.ItemSorter",
+ "com.vaadin.data.util.MethodProperty",
+ "com.vaadin.data.util.ObjectProperty",
+ "com.vaadin.data.util.PropertyFormatter",
+ "com.vaadin.data.util.PropertysetItem",
+ "com.vaadin.data.util.QueryContainer",
+ "com.vaadin.data.util.TextFileProperty",
+ "com.vaadin.data.Validatable",
+ "com.vaadin.data.validator.AbstractStringValidator",
+ "com.vaadin.data.validator.AbstractValidator",
+ "com.vaadin.data.validator.CompositeValidator",
+ "com.vaadin.data.validator.DoubleValidator",
+ "com.vaadin.data.validator.EmailValidator",
+ "com.vaadin.data.validator.IntegerValidator",
+ "com.vaadin.data.validator.NullValidator",
+ "com.vaadin.data.validator.RegexpValidator",
+ "com.vaadin.data.validator.StringLengthValidator",
+ "com.vaadin.data.Validator", "com.vaadin.event.Action",
+ "com.vaadin.event.ComponentEventListener",
+ "com.vaadin.event.EventRouter", "com.vaadin.event.FieldEvents",
+ "com.vaadin.event.ItemClickEvent", "com.vaadin.event.LayoutEvents",
+ "com.vaadin.event.ListenerMethod",
+ "com.vaadin.event.MethodEventSource",
+ "com.vaadin.event.MouseEvents", "com.vaadin.event.ShortcutAction",
+ "com.vaadin.launcher.DemoLauncher",
+ "com.vaadin.launcher.DevelopmentServerLauncher",
+ "com.vaadin.launcher.util.BrowserLauncher",
+ "com.vaadin.service.ApplicationContext",
+ "com.vaadin.service.FileTypeResolver",
+ "com.vaadin.server.ApplicationResource",
+ "com.vaadin.server.ClassResource",
+ "com.vaadin.server.CompositeErrorMessage",
+ "com.vaadin.server.DownloadStream",
+ "com.vaadin.server.ErrorMessage",
+ "com.vaadin.server.ExternalResource",
+ "com.vaadin.server.FileResource",
+ "com.vaadin.terminal.gwt.client.ApplicationConfiguration",
+ "com.vaadin.terminal.gwt.client.ApplicationConnection",
+ "com.vaadin.terminal.gwt.client.BrowserInfo",
+ "com.vaadin.terminal.gwt.client.ClientExceptionHandler",
+ "com.vaadin.terminal.gwt.client.ComponentDetail",
+ "com.vaadin.terminal.gwt.client.ComponentDetailMap",
+ "com.vaadin.terminal.gwt.client.ComponentLocator",
+ "com.vaadin.terminal.gwt.client.Console",
+ "com.vaadin.terminal.gwt.client.Container",
+ "com.vaadin.terminal.gwt.client.ContainerResizedListener",
+ "com.vaadin.terminal.gwt.client.CSSRule",
+ "com.vaadin.terminal.gwt.client.DateTimeService",
+ "com.vaadin.terminal.gwt.client.DefaultWidgetSet",
+ "com.vaadin.terminal.gwt.client.Focusable",
+ "com.vaadin.terminal.gwt.client.HistoryImplIEVaadin",
+ "com.vaadin.terminal.gwt.client.LocaleNotLoadedException",
+ "com.vaadin.terminal.gwt.client.LocaleService",
+ "com.vaadin.terminal.gwt.client.MouseEventDetails",
+ "com.vaadin.terminal.gwt.client.NullConsole",
+ "com.vaadin.terminal.gwt.client.Paintable",
+ "com.vaadin.terminal.gwt.client.RenderInformation",
+ "com.vaadin.terminal.gwt.client.RenderSpace",
+ "com.vaadin.terminal.gwt.client.StyleConstants",
+ "com.vaadin.terminal.gwt.client.TooltipInfo",
+ "com.vaadin.terminal.gwt.client.ui.Action",
+ "com.vaadin.terminal.gwt.client.ui.ActionOwner",
+ "com.vaadin.terminal.gwt.client.ui.AlignmentInfo",
+ "com.vaadin.terminal.gwt.client.ui.CalendarEntry",
+ "com.vaadin.terminal.gwt.client.ui.ClickEventHandler",
+ "com.vaadin.terminal.gwt.client.ui.Field",
+ "com.vaadin.terminal.gwt.client.ui.Icon",
+ "com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayout",
+ "com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer",
+ "com.vaadin.terminal.gwt.client.ui.layout.Margins",
+ "com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler",
+ "com.vaadin.terminal.gwt.client.ui.MenuBar",
+ "com.vaadin.terminal.gwt.client.ui.MenuItem",
+ "com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextToolbar",
+ "com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler",
+ "com.vaadin.terminal.gwt.client.ui.SubPartAware",
+ "com.vaadin.terminal.gwt.client.ui.Table",
+ "com.vaadin.terminal.gwt.client.ui.TreeAction",
+ "com.vaadin.terminal.gwt.client.ui.TreeImages",
+ "com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout",
+ "com.vaadin.terminal.gwt.client.ui.VAccordion",
+ "com.vaadin.terminal.gwt.client.ui.VButton",
+ "com.vaadin.terminal.gwt.client.ui.VCalendarPanel",
+ "com.vaadin.terminal.gwt.client.ui.VCheckBox",
+ "com.vaadin.terminal.gwt.client.ui.VContextMenu",
+ "com.vaadin.terminal.gwt.client.ui.VCssLayout",
+ "com.vaadin.terminal.gwt.client.ui.VCustomComponent",
+ "com.vaadin.terminal.gwt.client.ui.VCustomLayout",
+ "com.vaadin.terminal.gwt.client.ui.VDateField",
+ "com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar",
+ "com.vaadin.terminal.gwt.client.ui.VEmbedded",
+ "com.vaadin.terminal.gwt.client.ui.VFilterSelect",
+ "com.vaadin.terminal.gwt.client.ui.VForm",
+ "com.vaadin.terminal.gwt.client.ui.VFormLayout",
+ "com.vaadin.terminal.gwt.client.ui.VGridLayout",
+ "com.vaadin.terminal.gwt.client.ui.VHorizontalLayout",
+ "com.vaadin.terminal.gwt.client.ui.VLabel",
+ "com.vaadin.terminal.gwt.client.ui.VLink",
+ "com.vaadin.terminal.gwt.client.ui.VListSelect",
+ "com.vaadin.terminal.gwt.client.ui.VMarginInfo",
+ "com.vaadin.terminal.gwt.client.ui.VMenuBar",
+ "com.vaadin.terminal.gwt.client.ui.VNativeButton",
+ "com.vaadin.terminal.gwt.client.ui.VNativeSelect",
+ "com.vaadin.terminal.gwt.client.ui.VNotification",
+ "com.vaadin.terminal.gwt.client.ui.VOptionGroup",
+ "com.vaadin.terminal.gwt.client.ui.VOptionGroupBase",
+ "com.vaadin.terminal.gwt.client.ui.VOrderedLayout",
+ "com.vaadin.terminal.gwt.client.ui.VOverlay",
+ "com.vaadin.terminal.gwt.client.ui.VPanel",
+ "com.vaadin.terminal.gwt.client.ui.VPasswordField",
+ "com.vaadin.terminal.gwt.client.ui.VPopupCalendar",
+ "com.vaadin.terminal.gwt.client.ui.VPopupView",
+ "com.vaadin.terminal.gwt.client.ui.VProgressIndicator",
+ "com.vaadin.terminal.gwt.client.ui.VRichTextArea",
+ "com.vaadin.terminal.gwt.client.ui.VScrollTable",
+ "com.vaadin.terminal.gwt.client.ui.VSlider",
+ "com.vaadin.terminal.gwt.client.ui.VSplitPanel",
+ "com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal",
+ "com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical",
+ "com.vaadin.terminal.gwt.client.ui.VTablePaging",
+ "com.vaadin.terminal.gwt.client.ui.VTabsheet",
+ "com.vaadin.terminal.gwt.client.ui.VTabsheetBase",
+ "com.vaadin.terminal.gwt.client.ui.VTabsheetPanel",
+ "com.vaadin.terminal.gwt.client.ui.VTextArea",
+ "com.vaadin.terminal.gwt.client.ui.VTextField",
+ "com.vaadin.terminal.gwt.client.ui.VTextualDate",
+ "com.vaadin.terminal.gwt.client.ui.VTime",
+ "com.vaadin.terminal.gwt.client.ui.VTree",
+ "com.vaadin.terminal.gwt.client.ui.VTwinColSelect",
+ "com.vaadin.terminal.gwt.client.ui.VUnknownComponent",
+ "com.vaadin.terminal.gwt.client.ui.VUpload",
+ "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility",
+ "com.vaadin.terminal.gwt.client.ui.VVerticalLayout",
+ "com.vaadin.terminal.gwt.client.ui.VView",
+ "com.vaadin.terminal.gwt.client.ui.VWindow",
+ "com.vaadin.terminal.gwt.client.UIDL",
+ "com.vaadin.terminal.gwt.client.Util",
+ "com.vaadin.terminal.gwt.client.ValueMap",
+ "com.vaadin.terminal.gwt.client.VCaption",
+ "com.vaadin.terminal.gwt.client.VCaptionWrapper",
+ "com.vaadin.terminal.gwt.client.VDebugConsole",
+ "com.vaadin.terminal.gwt.client.VErrorMessage",
+ "com.vaadin.terminal.gwt.client.VTooltip",
+ "com.vaadin.terminal.gwt.client.VUIDLBrowser",
+ "com.vaadin.terminal.gwt.client.WidgetMap",
+ "com.vaadin.terminal.gwt.client.WidgetSet",
+ "com.vaadin.server.AbstractApplicationPortlet",
+ "com.vaadin.server.AbstractApplicationServlet",
+ "com.vaadin.server.AbstractCommunicationManager",
+ "com.vaadin.server.AbstractWebApplicationContext",
+ "com.vaadin.server.ApplicationPortlet",
+ "com.vaadin.server.ApplicationPortlet2",
+ "com.vaadin.server.ApplicationRunnerServlet",
+ "com.vaadin.server.ApplicationServlet",
+ "com.vaadin.server.ChangeVariablesErrorEvent",
+ "com.vaadin.server.CommunicationManager",
+ "com.vaadin.server.ComponentSizeValidator",
+ "com.vaadin.server.Constants",
+ "com.vaadin.server.GAEApplicationServlet",
+ "com.vaadin.server.HttpServletRequestListener",
+ "com.vaadin.server.HttpUploadStream",
+ "com.vaadin.server.JsonPaintTarget",
+ "com.vaadin.server.PortletApplicationContext",
+ "com.vaadin.server.PortletApplicationContext2",
+ "com.vaadin.server.PortletCommunicationManager",
+ "com.vaadin.server.PortletRequestListener",
+ "com.vaadin.server.RestrictedRenderResponse",
+ "com.vaadin.server.SessionExpiredException",
+ "com.vaadin.server.SystemMessageException",
+ "com.vaadin.server.WebApplicationContext",
+ "com.vaadin.server.WebBrowser",
+ "com.vaadin.server.widgetsetutils.ClassPathExplorer",
+ "com.vaadin.server.widgetsetutils.WidgetMapGenerator",
+ "com.vaadin.server.widgetsetutils.WidgetSetBuilder",
+ "com.vaadin.server.KeyMapper", "com.vaadin.server.Paintable",
+ "com.vaadin.server.PaintException", "com.vaadin.server.PaintTarget",
+ "com.vaadin.server.ParameterHandler", "com.vaadin.server.Resource",
+ "com.vaadin.server.Scrollable", "com.vaadin.server.Sizeable",
+ "com.vaadin.server.StreamResource", "com.vaadin.server.SystemError",
+ "com.vaadin.server.Terminal", "com.vaadin.server.ThemeResource",
+ "com.vaadin.server.UploadStream", "com.vaadin.server.URIHandler",
+ "com.vaadin.server.UserError", "com.vaadin.server.VariableOwner",
+ "com.vaadin.tools.ReflectTools",
+ "com.vaadin.tools.WidgetsetCompiler",
+ "com.vaadin.ui.AbsoluteLayout", "com.vaadin.ui.AbstractComponent",
+ "com.vaadin.ui.AbstractComponentContainer",
+ "com.vaadin.ui.AbstractField", "com.vaadin.ui.AbstractLayout",
+ "com.vaadin.ui.AbstractOrderedLayout",
+ "com.vaadin.ui.AbstractSelect", "com.vaadin.ui.Accordion",
+ "com.vaadin.ui.Alignment", "com.vaadin.ui.AlignmentUtils",
+ "com.vaadin.ui.BaseFieldFactory", "com.vaadin.ui.Button",
+ "com.vaadin.ui.CheckBox", "com.vaadin.ui.ClientWidget",
+ "com.vaadin.ui.ComboBox", "com.vaadin.ui.Component",
+ "com.vaadin.ui.ComponentContainer", "com.vaadin.ui.CssLayout",
+ "com.vaadin.ui.CustomComponent", "com.vaadin.ui.CustomLayout",
+ "com.vaadin.ui.DateField", "com.vaadin.ui.DefaultFieldFactory",
+ "com.vaadin.ui.Embedded", "com.vaadin.ui.ExpandLayout",
+ "com.vaadin.ui.Field", "com.vaadin.ui.FieldFactory",
+ "com.vaadin.ui.Form", "com.vaadin.ui.FormFieldFactory",
+ "com.vaadin.ui.FormLayout", "com.vaadin.ui.GridLayout",
+ "com.vaadin.ui.HorizontalLayout", "com.vaadin.ui.InlineDateField",
+ "com.vaadin.ui.Label", "com.vaadin.ui.Layout", "com.vaadin.ui.Link",
+ "com.vaadin.ui.ListSelect", "com.vaadin.ui.LoginForm",
+ "com.vaadin.ui.MenuBar", "com.vaadin.ui.NativeButton",
+ "com.vaadin.ui.NativeSelect", "com.vaadin.ui.OptionGroup",
+ "com.vaadin.ui.OrderedLayout", "com.vaadin.ui.Panel",
+ "com.vaadin.ui.PopupDateField", "com.vaadin.ui.PopupView",
+ "com.vaadin.ui.ProgressIndicator", "com.vaadin.ui.RichTextArea",
+ "com.vaadin.ui.Select", "com.vaadin.ui.Slider",
+ "com.vaadin.ui.SplitPanel", "com.vaadin.ui.Table",
+ "com.vaadin.ui.TableFieldFactory", "com.vaadin.ui.TabSheet",
+ "com.vaadin.ui.TextField", "com.vaadin.ui.Tree",
+ "com.vaadin.ui.TwinColSelect", "com.vaadin.ui.Upload",
+ "com.vaadin.ui.UriFragmentUtility", "com.vaadin.ui.VerticalLayout",
+ "com.vaadin.ui.Window", "com.vaadin.util.SerializerHelper",
+ "org.vaadin.test.LastClass" };
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java
new file mode 100644
index 0000000000..f3eda74100
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java
@@ -0,0 +1,289 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Hierarchical;
+import com.vaadin.data.Container.Sortable;
+import com.vaadin.data.Item;
+
+public abstract class AbstractHierarchicalContainerTestBase
+ extends AbstractContainerTestBase {
+
+ /**
+ * @param container
+ * The container to validate
+ * @param expectedFirstItemId
+ * Expected first item id
+ * @param expectedLastItemId
+ * Expected last item id
+ * @param itemIdInSet
+ * An item id that is in the container
+ * @param itemIdNotInSet
+ * An item id that is not in the container
+ * @param checkGetItemNull
+ * true if getItem() should return null for itemIdNotInSet, false
+ * to skip the check (container.containsId() is checked in any
+ * case)
+ * @param expectedSize
+ * Expected number of items in the container. Not related to
+ * hierarchy.
+ * @param expectedTraversalSize
+ * Expected number of items found when traversing from the roots
+ * down to all available nodes.
+ * @param expectedRootSize
+ * Expected number of root items
+ * @param rootsHaveChildren
+ * true if all roots have children, false otherwise (skips some
+ * asserts)
+ */
+ protected void validateHierarchicalContainer(Hierarchical container,
+ Object expectedFirstItemId, Object expectedLastItemId,
+ Object itemIdInSet, Object itemIdNotInSet, boolean checkGetItemNull,
+ int expectedSize, int expectedRootSize, boolean rootsHaveChildren) {
+
+ validateContainer(container, expectedFirstItemId, expectedLastItemId,
+ itemIdInSet, itemIdNotInSet, checkGetItemNull, expectedSize);
+
+ // rootItemIds
+ Collection<?> rootIds = container.rootItemIds();
+ assertEquals(expectedRootSize, rootIds.size());
+
+ for (Object rootId : rootIds) {
+ // All roots must be in container
+ assertTrue(container.containsId(rootId));
+
+ // All roots must have no parent
+ assertNull(container.getParent(rootId));
+
+ // all roots must be roots
+ assertTrue(container.isRoot(rootId));
+
+ if (rootsHaveChildren) {
+ // all roots have children allowed in this case
+ assertTrue(container.areChildrenAllowed(rootId));
+
+ // all roots have children in this case
+ Collection<?> children = container.getChildren(rootId);
+ assertNotNull(rootId + " should have children", children);
+ assertTrue(rootId + " should have children",
+ (children.size() > 0));
+ // getParent
+ for (Object childId : children) {
+ assertEquals(container.getParent(childId), rootId);
+ }
+
+ }
+ }
+
+ // isRoot should return false for unknown items
+ assertFalse(container.isRoot(itemIdNotInSet));
+
+ // hasChildren should return false for unknown items
+ assertFalse(container.hasChildren(itemIdNotInSet));
+
+ // areChildrenAllowed should return false for unknown items
+ assertFalse(container.areChildrenAllowed(itemIdNotInSet));
+
+ // removeItem of unknown items should return false
+ assertFalse(container.removeItem(itemIdNotInSet));
+
+ assertEquals(expectedSize, countNodes(container));
+
+ validateHierarchy(container);
+ }
+
+ private int countNodes(Hierarchical container) {
+ int totalNodes = 0;
+ for (Object rootId : container.rootItemIds()) {
+ totalNodes += countNodes(container, rootId);
+ }
+
+ return totalNodes;
+ }
+
+ private int countNodes(Hierarchical container, Object itemId) {
+ int nodes = 1; // This
+ Collection<?> children = container.getChildren(itemId);
+ if (children != null) {
+ for (Object id : children) {
+ nodes += countNodes(container, id);
+ }
+ }
+
+ return nodes;
+ }
+
+ private void validateHierarchy(Hierarchical container) {
+ for (Object rootId : container.rootItemIds()) {
+ validateHierarchy(container, rootId, null);
+ }
+ }
+
+ private void validateHierarchy(Hierarchical container, Object itemId,
+ Object parentId) {
+ Collection<?> children = container.getChildren(itemId);
+
+ // getParent
+ assertEquals(container.getParent(itemId), parentId);
+
+ if (!container.areChildrenAllowed(itemId)) {
+ // If no children is allowed the item should have no children
+ assertFalse(container.hasChildren(itemId));
+ assertTrue(children == null || children.size() == 0);
+
+ return;
+ }
+ if (children != null) {
+ for (Object id : children) {
+ validateHierarchy(container, id, itemId);
+ }
+ }
+ }
+
+ protected void testHierarchicalContainer(Container.Hierarchical container) {
+ initializeContainer(container);
+
+ int packages = 21 + 3;
+ int expectedSize = sampleData.length + packages;
+ validateHierarchicalContainer(container, "com",
+ "org.vaadin.test.LastClass",
+ "com.vaadin.server.ApplicationResource", "blah", true,
+ expectedSize, 2, true);
+
+ }
+
+ protected void testHierarchicalSorting(Container.Hierarchical container) {
+ Container.Sortable sortable = (Sortable) container;
+
+ initializeContainer(container);
+
+ // Must be able to sort based on PROP1 and PROP2 for this test
+ assertTrue(sortable.getSortableContainerPropertyIds()
+ .contains(FULLY_QUALIFIED_NAME));
+ assertTrue(sortable.getSortableContainerPropertyIds()
+ .contains(REVERSE_FULLY_QUALIFIED_NAME));
+
+ sortable.sort(new Object[] { FULLY_QUALIFIED_NAME },
+ new boolean[] { true });
+
+ int packages = 21 + 3;
+ int expectedSize = sampleData.length + packages;
+ validateHierarchicalContainer(container, "com",
+ "org.vaadin.test.LastClass",
+ "com.vaadin.server.ApplicationResource", "blah", true,
+ expectedSize, 2, true);
+
+ sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME },
+ new boolean[] { true });
+
+ validateHierarchicalContainer(container,
+ "com.vaadin.server.ApplicationPortlet2",
+ "com.vaadin.data.util.ObjectProperty",
+ "com.vaadin.server.ApplicationResource", "blah", true,
+ expectedSize, 2, true);
+
+ }
+
+ protected void initializeContainer(Container.Hierarchical container) {
+ container.removeAllItems();
+ Object[] propertyIds = container.getContainerPropertyIds().toArray();
+ for (Object propertyId : propertyIds) {
+ container.removeContainerProperty(propertyId);
+ }
+
+ container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, "");
+ container.addContainerProperty(SIMPLE_NAME, String.class, "");
+ container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME,
+ String.class, null);
+ container.addContainerProperty(ID_NUMBER, Integer.class, null);
+
+ for (int i = 0; i < sampleData.length; i++) {
+ String id = sampleData[i];
+
+ // Add path as parent
+ String paths[] = id.split("\\.");
+ String path = paths[0];
+ // Adds "com" and other items multiple times so should return null
+ // for all but the first time
+ if (container.addItem(path) != null) {
+ assertTrue(container.setChildrenAllowed(path, false));
+ Item item = container.getItem(path);
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path);
+ item.getItemProperty(SIMPLE_NAME).setValue(getSimpleName(path));
+ item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME)
+ .setValue(reverse(path));
+ item.getItemProperty(ID_NUMBER).setValue(1);
+ }
+ for (int j = 1; j < paths.length; j++) {
+ String parent = path;
+ path = path + "." + paths[j];
+
+ // Adds "com" and other items multiple times so should return
+ // null for all but the first time
+ if (container.addItem(path) != null) {
+ assertTrue(container.setChildrenAllowed(path, false));
+
+ Item item = container.getItem(path);
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path);
+ item.getItemProperty(SIMPLE_NAME)
+ .setValue(getSimpleName(path));
+ item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME)
+ .setValue(reverse(path));
+ item.getItemProperty(ID_NUMBER).setValue(1);
+
+ }
+ assertTrue(container.setChildrenAllowed(parent, true));
+ assertTrue("Failed to set " + parent + " as parent for " + path,
+ container.setParent(path, parent));
+ }
+
+ Item item = container.getItem(id);
+ assertNotNull(item);
+ String parent = id.substring(0, id.lastIndexOf('.'));
+ assertTrue(container.setParent(id, parent));
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]);
+ item.getItemProperty(SIMPLE_NAME)
+ .setValue(getSimpleName(sampleData[i]));
+ item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME)
+ .setValue(reverse(sampleData[i]));
+ item.getItemProperty(ID_NUMBER).setValue(i % 2);
+ }
+ }
+
+ protected void testRemoveHierarchicalWrapperSubtree(
+ Container.Hierarchical container) {
+ initializeContainer(container);
+
+ // remove root item
+ removeItemRecursively(container, "org");
+
+ int packages = 21 + 3 - 3;
+ int expectedSize = sampleData.length + packages - 1;
+
+ validateContainer(container, "com", "com.vaadin.util.SerializerHelper",
+ "com.vaadin.server.ApplicationResource", "blah", true,
+ expectedSize);
+
+ // rootItemIds
+ Collection<?> rootIds = container.rootItemIds();
+ assertEquals(1, rootIds.size());
+ }
+
+ private void removeItemRecursively(Container.Hierarchical container,
+ Object itemId) {
+ if (container instanceof ContainerHierarchicalWrapper) {
+ ((ContainerHierarchicalWrapper) container)
+ .removeItemRecursively("org");
+ } else {
+ HierarchicalContainer.removeItemRecursively(container, itemId);
+ }
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java
new file mode 100644
index 0000000000..3858504bc7
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java
@@ -0,0 +1,6 @@
+package com.vaadin.data.util;
+
+public abstract class AbstractInMemoryContainerTestBase
+ extends AbstractContainerTestBase {
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java
new file mode 100644
index 0000000000..bdf6ba1958
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java
@@ -0,0 +1,516 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+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.AbstractBeanContainer.BeanIdResolver;
+
+public class BeanContainerTest extends AbstractBeanContainerTestBase {
+
+ protected static class PersonNameResolver
+ implements BeanIdResolver<String, Person> {
+
+ @Override
+ public String getIdForBean(Person bean) {
+ return bean != null ? bean.getName() : null;
+ }
+
+ }
+
+ protected static class NullResolver
+ implements BeanIdResolver<String, Person> {
+
+ @Override
+ public String getIdForBean(Person bean) {
+ return null;
+ }
+
+ }
+
+ private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>();
+
+ private BeanContainer<String, ClassName> getContainer() {
+ return new BeanContainer<String, ClassName>(ClassName.class);
+ }
+
+ @Before
+ public void setUp() {
+ nameToBean.clear();
+
+ for (int i = 0; i < sampleData.length; i++) {
+ ClassName className = new ClassName(sampleData[i], i);
+ nameToBean.put(sampleData[i], className);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void initializeContainer(Container container) {
+ BeanContainer<String, ClassName> beanItemContainer = (BeanContainer<String, ClassName>) container;
+
+ beanItemContainer.removeAllItems();
+
+ for (Entry<String, ClassName> entry : nameToBean.entrySet()) {
+ beanItemContainer.addItem(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ protected boolean isFilteredOutItemNull() {
+ return false;
+ }
+
+ @Test
+ public void testGetType_existingProperty_typeReturned() {
+ BeanContainer<String, ClassName> container = getContainer();
+ Assert.assertEquals(
+ "Unexpected type is returned for property 'simpleName'",
+ String.class, container.getType("simpleName"));
+ }
+
+ @Test
+ public void testGetType_notExistingProperty_nullReturned() {
+ BeanContainer<String, ClassName> container = getContainer();
+ Assert.assertNull("Not null type is returned for property ''",
+ container.getType(""));
+ }
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(getContainer());
+ }
+
+ @Test
+ public void testFiltering() {
+ testContainerFiltering(getContainer());
+ }
+
+ @Test
+ public void testSorting() {
+ testContainerSorting(getContainer());
+ }
+
+ @Test
+ public void testSortingAndFiltering() {
+ testContainerSortingAndFiltering(getContainer());
+ }
+
+ // duplicated from parent class and modified - adding items to
+ // BeanContainer differs from other containers
+ @Test
+ public void testContainerOrdered() {
+ BeanContainer<String, String> container = new BeanContainer<String, String>(
+ String.class);
+
+ String id = "test1";
+
+ Item item = container.addItem(id, "value");
+ assertNotNull(item);
+
+ assertEquals(id, container.firstItemId());
+ assertEquals(id, container.lastItemId());
+
+ // isFirstId
+ assertTrue(container.isFirstId(id));
+ assertTrue(container.isFirstId(container.firstItemId()));
+ // isLastId
+ assertTrue(container.isLastId(id));
+ assertTrue(container.isLastId(container.lastItemId()));
+
+ // Add a new item before the first
+ // addItemAfter
+ String newFirstId = "newFirst";
+ item = container.addItemAfter(null, newFirstId, "newFirstValue");
+ assertNotNull(item);
+ assertNotNull(container.getItem(newFirstId));
+
+ // isFirstId
+ assertTrue(container.isFirstId(newFirstId));
+ assertTrue(container.isFirstId(container.firstItemId()));
+ // isLastId
+ assertTrue(container.isLastId(id));
+ assertTrue(container.isLastId(container.lastItemId()));
+
+ // nextItemId
+ assertEquals(id, container.nextItemId(newFirstId));
+ assertNull(container.nextItemId(id));
+ assertNull(container.nextItemId("not-in-container"));
+
+ // prevItemId
+ assertEquals(newFirstId, container.prevItemId(id));
+ assertNull(container.prevItemId(newFirstId));
+ assertNull(container.prevItemId("not-in-container"));
+
+ // addItemAfter(IDTYPE, IDTYPE, BT)
+ String newSecondItemId = "newSecond";
+ item = container.addItemAfter(newFirstId, newSecondItemId,
+ "newSecondValue");
+ // order is now: newFirstId, newSecondItemId, id
+ assertNotNull(item);
+ assertNotNull(container.getItem(newSecondItemId));
+ assertEquals(id, container.nextItemId(newSecondItemId));
+ assertEquals(newFirstId, container.prevItemId(newSecondItemId));
+
+ // addItemAfter(IDTYPE, IDTYPE, BT)
+ String fourthId = "id of the fourth item";
+ Item fourth = container.addItemAfter(newFirstId, fourthId,
+ "fourthValue");
+ // order is now: newFirstId, fourthId, newSecondItemId, id
+ assertNotNull(fourth);
+ assertEquals(fourth, container.getItem(fourthId));
+ assertEquals(newSecondItemId, container.nextItemId(fourthId));
+ assertEquals(newFirstId, container.prevItemId(fourthId));
+
+ // addItemAfter(IDTYPE, IDTYPE, BT)
+ String fifthId = "fifth";
+ Item fifth = container.addItemAfter(null, fifthId, "fifthValue");
+ // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id
+ assertNotNull(fifth);
+ assertEquals(fifth, container.getItem(fifthId));
+ assertEquals(newFirstId, container.nextItemId(fifthId));
+ assertNull(container.prevItemId(fifthId));
+
+ }
+
+ // TODO test Container.Indexed interface operation - testContainerIndexed()?
+
+ @Test
+ public void testAddItemAt() {
+ BeanContainer<String, String> container = new BeanContainer<String, String>(
+ String.class);
+
+ container.addItem("id1", "value1");
+ // id1
+ container.addItemAt(0, "id2", "value2");
+ // id2, id1
+ container.addItemAt(1, "id3", "value3");
+ // id2, id3, id1
+ container.addItemAt(container.size(), "id4", "value4");
+ // id2, id3, id1, id4
+
+ assertNull(container.addItemAt(-1, "id5", "value5"));
+ assertNull(container.addItemAt(container.size() + 1, "id6", "value6"));
+
+ assertEquals(4, container.size());
+ assertEquals("id2", container.getIdByIndex(0));
+ assertEquals("id3", container.getIdByIndex(1));
+ assertEquals("id1", container.getIdByIndex(2));
+ assertEquals("id4", container.getIdByIndex(3));
+ }
+
+ @Test
+ public void testUnsupportedMethods() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ container.addItem("John", new Person("John"));
+
+ try {
+ container.addItem();
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItem(null);
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItemAfter(null, null);
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItemAfter(new Person("Jane"));
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItemAt(0);
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItemAt(0, new Person("Jane"));
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addContainerProperty("lastName", String.class, "");
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ assertEquals(1, container.size());
+ }
+
+ @Test
+ public void testRemoveContainerProperty() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ container.setBeanIdResolver(new PersonNameResolver());
+ container.addBean(new Person("John"));
+
+ Assert.assertEquals("John",
+ container.getContainerProperty("John", "name").getValue());
+ Assert.assertTrue(container.removeContainerProperty("name"));
+ Assert.assertNull(container.getContainerProperty("John", "name"));
+
+ Assert.assertNotNull(container.getItem("John"));
+ // property removed also from item
+ Assert.assertNull(container.getItem("John").getItemProperty("name"));
+ }
+
+ @Test
+ public void testAddNullBeans() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+
+ assertNull(container.addItem("id1", null));
+ assertNull(container.addItemAfter(null, "id2", null));
+ assertNull(container.addItemAt(0, "id3", null));
+
+ assertEquals(0, container.size());
+ }
+
+ @Test
+ public void testAddNullId() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+
+ Person john = new Person("John");
+
+ assertNull(container.addItem(null, john));
+ assertNull(container.addItemAfter(null, null, john));
+ assertNull(container.addItemAt(0, null, john));
+
+ assertEquals(0, container.size());
+ }
+
+ @Test
+ public void testEmptyContainer() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+
+ assertNull(container.firstItemId());
+ assertNull(container.lastItemId());
+
+ assertEquals(0, container.size());
+
+ // could test more about empty container
+ }
+
+ @Test
+ public void testAddBeanWithoutResolver() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+
+ try {
+ container.addBean(new Person("John"));
+ Assert.fail();
+ } catch (IllegalStateException e) {
+ // should get exception
+ }
+ try {
+ container.addBeanAfter(null, new Person("Jane"));
+ Assert.fail();
+ } catch (IllegalStateException e) {
+ // should get exception
+ }
+ try {
+ container.addBeanAt(0, new Person("Jack"));
+ Assert.fail();
+ } catch (IllegalStateException e) {
+ // should get exception
+ }
+ try {
+ container
+ .addAll(Arrays.asList(new Person[] { new Person("Jack") }));
+ Assert.fail();
+ } catch (IllegalStateException e) {
+ // should get exception
+ }
+
+ assertEquals(0, container.size());
+ }
+
+ @Test
+ public void testAddAllWithNullItemId() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ // resolver that returns null as item id
+ container.setBeanIdResolver(
+ new BeanIdResolver<String, AbstractBeanContainerTestBase.Person>() {
+
+ @Override
+ public String getIdForBean(Person bean) {
+ return bean.getName();
+ }
+ });
+
+ List<Person> persons = new ArrayList<Person>();
+ persons.add(new Person("John"));
+ persons.add(new Person("Marc"));
+ persons.add(new Person(null));
+ persons.add(new Person("foo"));
+
+ try {
+ container.addAll(persons);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+
+ container.removeAllItems();
+ persons.remove(2);
+ container.addAll(persons);
+ assertEquals(3, container.size());
+ }
+
+ @Test
+ public void testAddBeanWithNullResolver() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ // resolver that returns null as item id
+ container.setBeanIdResolver(new NullResolver());
+
+ try {
+ container.addBean(new Person("John"));
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ try {
+ container.addBeanAfter(null, new Person("Jane"));
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ try {
+ container.addBeanAt(0, new Person("Jack"));
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+
+ assertEquals(0, container.size());
+ }
+
+ @Test
+ public void testAddBeanWithResolver() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ container.setBeanIdResolver(new PersonNameResolver());
+
+ assertNotNull(container.addBean(new Person("John")));
+ assertNotNull(container.addBeanAfter(null, new Person("Jane")));
+ assertNotNull(container.addBeanAt(0, new Person("Jack")));
+
+ container.addAll(Arrays.asList(
+ new Person[] { new Person("Jill"), new Person("Joe") }));
+
+ assertTrue(container.containsId("John"));
+ assertTrue(container.containsId("Jane"));
+ assertTrue(container.containsId("Jack"));
+ assertTrue(container.containsId("Jill"));
+ assertTrue(container.containsId("Joe"));
+ assertEquals(3, container.indexOfId("Jill"));
+ assertEquals(4, container.indexOfId("Joe"));
+ assertEquals(5, container.size());
+ }
+
+ @Test
+ public void testAddNullBeansWithResolver() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ container.setBeanIdResolver(new PersonNameResolver());
+
+ assertNull(container.addBean(null));
+ assertNull(container.addBeanAfter(null, null));
+ assertNull(container.addBeanAt(0, null));
+
+ assertEquals(0, container.size());
+ }
+
+ @Test
+ public void testAddBeanWithPropertyResolver() {
+ BeanContainer<String, Person> container = new BeanContainer<String, Person>(
+ Person.class);
+ container.setBeanIdProperty("name");
+
+ assertNotNull(container.addBean(new Person("John")));
+ assertNotNull(container.addBeanAfter(null, new Person("Jane")));
+ assertNotNull(container.addBeanAt(0, new Person("Jack")));
+
+ container.addAll(Arrays.asList(
+ new Person[] { new Person("Jill"), new Person("Joe") }));
+
+ assertTrue(container.containsId("John"));
+ assertTrue(container.containsId("Jane"));
+ assertTrue(container.containsId("Jack"));
+ assertTrue(container.containsId("Jill"));
+ assertTrue(container.containsId("Joe"));
+ assertEquals(3, container.indexOfId("Jill"));
+ assertEquals(4, container.indexOfId("Joe"));
+ assertEquals(5, container.size());
+ }
+
+ @Test
+ public void testAddNestedContainerProperty() {
+ BeanContainer<String, NestedMethodPropertyTest.Person> container = new BeanContainer<String, NestedMethodPropertyTest.Person>(
+ NestedMethodPropertyTest.Person.class);
+ container.setBeanIdProperty("name");
+
+ container.addBean(new NestedMethodPropertyTest.Person("John",
+ new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", 20540)));
+
+ assertTrue(container.addNestedContainerProperty("address.street"));
+ assertEquals("Ruukinkatu 2-4", container
+ .getContainerProperty("John", "address.street").getValue());
+ }
+
+ @Test
+ public void testNestedContainerPropertyWithNullBean() {
+ BeanContainer<String, NestedMethodPropertyTest.Person> container = new BeanContainer<String, NestedMethodPropertyTest.Person>(
+ NestedMethodPropertyTest.Person.class);
+ container.setBeanIdProperty("name");
+
+ container.addBean(new NestedMethodPropertyTest.Person("John", null));
+ assertTrue(container
+ .addNestedContainerProperty("address.postalCodeObject"));
+ assertTrue(container.addNestedContainerProperty("address.street"));
+ // the nested properties added with allowNullBean setting should return
+ // null
+ assertNull(container.getContainerProperty("John", "address.street")
+ .getValue());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java
new file mode 100644
index 0000000000..a5bdcc7cf9
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java
@@ -0,0 +1,150 @@
+package com.vaadin.data.util;
+
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class BeanItemContainerGenerator {
+
+ public static class PortableRandom {
+ private final static long multiplier = 0x5DEECE66DL;
+ private final static long addend = 0xBL;
+ private final static long mask = (1L << 48) - 1;
+ private AtomicLong seed;
+
+ public PortableRandom(long seed) {
+ this.seed = new AtomicLong(0L);
+ setSeed(seed);
+ }
+
+ synchronized public void setSeed(long seed) {
+ seed = (seed ^ multiplier) & mask;
+ this.seed.set(seed);
+ }
+
+ public int nextInt(int n) {
+ if (n <= 0) {
+ throw new IllegalArgumentException("n must be positive");
+ }
+
+ if ((n & -n) == n) {
+ return (int) ((n * (long) next(31)) >> 31);
+ }
+
+ int bits, val;
+ do {
+ bits = next(31);
+ val = bits % n;
+ } while (bits - val + (n - 1) < 0);
+ return val;
+ }
+
+ protected int next(int bits) {
+ long oldseed, nextseed;
+ AtomicLong seed = this.seed;
+ do {
+ oldseed = seed.get();
+ nextseed = (oldseed * multiplier + addend) & mask;
+ } while (!seed.compareAndSet(oldseed, nextseed));
+ return (int) (nextseed >>> (48 - bits));
+ }
+
+ public boolean nextBoolean() {
+ return next(1) != 0;
+ }
+
+ }
+
+ public static BeanItemContainer<TestBean> createContainer(int size) {
+ return createContainer(size, new Date().getTime());
+ }
+
+ public static BeanItemContainer<TestBean> createContainer(int size,
+ long seed) {
+
+ BeanItemContainer<TestBean> container = new BeanItemContainer<TestBean>(
+ TestBean.class);
+ PortableRandom r = new PortableRandom(seed);
+ for (int i = 0; i < size; i++) {
+ container.addBean(new TestBean(r));
+ }
+
+ return container;
+
+ }
+
+ public static class TestBean {
+ private String name, address, city, country;
+ private int age, shoesize;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public int getShoesize() {
+ return shoesize;
+ }
+
+ public void setShoesize(int shoesize) {
+ this.shoesize = shoesize;
+ }
+
+ public TestBean(PortableRandom r) {
+ age = r.nextInt(100) + 5;
+ shoesize = r.nextInt(10) + 35;
+ name = createRandomString(r, r.nextInt(5) + 5);
+ address = createRandomString(r, r.nextInt(15) + 5) + " "
+ + r.nextInt(100) + 1;
+ city = createRandomString(r, r.nextInt(7) + 3);
+ if (r.nextBoolean()) {
+ country = createRandomString(r, r.nextInt(4) + 4);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ }
+
+ public static String createRandomString(PortableRandom r, int len) {
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < len; i++) {
+ b.append((char) (r.nextInt('z' - 'a') + 'a'));
+ }
+
+ return b.toString();
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java
new file mode 100644
index 0000000000..4f4e35258f
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java
@@ -0,0 +1,166 @@
+package com.vaadin.data.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BeanItemContainerSortTest {
+ public class Person {
+ private String name;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ private int age;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public class Parent extends Person {
+ private Set<Person> children = new HashSet<Person>();
+
+ public void setChildren(Set<Person> children) {
+ this.children = children;
+ }
+
+ public Set<Person> getChildren() {
+ return children;
+ }
+ }
+
+ String[] names = new String[] { "Antti", "Ville", "Sirkka", "Jaakko",
+ "Pekka", "John" };
+ int[] ages = new int[] { 10, 20, 50, 12, 64, 67 };
+ String[] sortedByAge = new String[] { names[0], names[3], names[1],
+ names[2], names[4], names[5] };
+
+ public BeanItemContainer<Person> getContainer() {
+ BeanItemContainer<Person> bc = new BeanItemContainer<Person>(
+ Person.class);
+ for (int i = 0; i < names.length; i++) {
+ Person p = new Person();
+ p.setName(names[i]);
+ p.setAge(ages[i]);
+ bc.addBean(p);
+ }
+ return bc;
+
+ }
+
+ public BeanItemContainer<Parent> getParentContainer() {
+ BeanItemContainer<Parent> bc = new BeanItemContainer<Parent>(
+ Parent.class);
+ for (int i = 0; i < names.length; i++) {
+ Parent p = new Parent();
+ p.setName(names[i]);
+ p.setAge(ages[i]);
+ bc.addBean(p);
+ }
+ return bc;
+ }
+
+ @Test
+ public void testSort() {
+ testSort(true);
+ }
+
+ public void testSort(boolean b) {
+ BeanItemContainer<Person> container = getContainer();
+ container.sort(new Object[] { "name" }, new boolean[] { b });
+
+ List<String> asList = Arrays.asList(names);
+ Collections.sort(asList);
+ if (!b) {
+ Collections.reverse(asList);
+ }
+
+ int i = 0;
+ for (String string : asList) {
+ Person idByIndex = container.getIdByIndex(i++);
+ Assert.assertTrue(container.containsId(idByIndex));
+ Assert.assertEquals(string, idByIndex.getName());
+ }
+ }
+
+ @Test
+ public void testReverseSort() {
+ testSort(false);
+ }
+
+ @Test
+ public void primitiveSorting() {
+ BeanItemContainer<Person> container = getContainer();
+ container.sort(new Object[] { "age" }, new boolean[] { true });
+
+ int i = 0;
+ for (String string : sortedByAge) {
+ Person idByIndex = container.getIdByIndex(i++);
+ Assert.assertTrue(container.containsId(idByIndex));
+ Assert.assertEquals(string, idByIndex.getName());
+ }
+ }
+
+ @Test
+ public void customSorting() {
+ BeanItemContainer<Person> container = getContainer();
+
+ // custom sorter using the reverse order
+ container.setItemSorter(new DefaultItemSorter() {
+ @Override
+ public int compare(Object o1, Object o2) {
+ return -super.compare(o1, o2);
+ }
+ });
+
+ container.sort(new Object[] { "age" }, new boolean[] { true });
+
+ int i = container.size() - 1;
+ for (String string : sortedByAge) {
+ Person idByIndex = container.getIdByIndex(i--);
+ Assert.assertTrue(container.containsId(idByIndex));
+ Assert.assertEquals(string, idByIndex.getName());
+ }
+ }
+
+ @Test
+ public void testGetSortableProperties() {
+ BeanItemContainer<Person> container = getContainer();
+
+ Collection<?> sortablePropertyIds = container
+ .getSortableContainerPropertyIds();
+ Assert.assertEquals(2, sortablePropertyIds.size());
+ Assert.assertTrue(sortablePropertyIds.contains("name"));
+ Assert.assertTrue(sortablePropertyIds.contains("age"));
+ }
+
+ @Test
+ public void testGetNonSortableProperties() {
+ BeanItemContainer<Parent> container = getParentContainer();
+
+ Assert.assertEquals(3, container.getContainerPropertyIds().size());
+
+ Collection<?> sortablePropertyIds = container
+ .getSortableContainerPropertyIds();
+ Assert.assertEquals(2, sortablePropertyIds.size());
+ Assert.assertTrue(sortablePropertyIds.contains("name"));
+ Assert.assertTrue(sortablePropertyIds.contains("age"));
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java
new file mode 100644
index 0000000000..19b0835fd6
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java
@@ -0,0 +1,997 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Indexed.ItemAddEvent;
+import com.vaadin.data.Container.Indexed.ItemRemoveEvent;
+import com.vaadin.data.Container.ItemSetChangeListener;
+import com.vaadin.data.Item;
+import com.vaadin.data.util.NestedMethodPropertyTest.Address;
+import com.vaadin.data.util.filter.Compare;
+
+/**
+ * Test basic functionality of BeanItemContainer.
+ *
+ * Most sorting related tests are in {@link BeanItemContainerSortTest}.
+ */
+public class BeanItemContainerTest extends AbstractBeanContainerTestBase {
+
+ // basics from the common container test
+
+ private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>();
+
+ private BeanItemContainer<ClassName> getContainer() {
+ return new BeanItemContainer<ClassName>(ClassName.class);
+ }
+
+ @Before
+ public void setUp() {
+ nameToBean.clear();
+
+ for (int i = 0; i < sampleData.length; i++) {
+ ClassName className = new ClassName(sampleData[i], i);
+ nameToBean.put(sampleData[i], className);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void initializeContainer(Container container) {
+ BeanItemContainer<ClassName> beanItemContainer = (BeanItemContainer<ClassName>) container;
+
+ beanItemContainer.removeAllItems();
+
+ Iterator<ClassName> it = nameToBean.values().iterator();
+ while (it.hasNext()) {
+ beanItemContainer.addBean(it.next());
+ }
+ }
+
+ @Override
+ protected void validateContainer(Container container,
+ Object expectedFirstItemId, Object expectedLastItemId,
+ Object itemIdInSet, Object itemIdNotInSet, boolean checkGetItemNull,
+ int expectedSize) {
+ Object notInSet = nameToBean.get(itemIdNotInSet);
+ if (notInSet == null && itemIdNotInSet != null) {
+ notInSet = new ClassName(String.valueOf(itemIdNotInSet), 9999);
+ }
+ super.validateContainer(container, nameToBean.get(expectedFirstItemId),
+ nameToBean.get(expectedLastItemId), nameToBean.get(itemIdInSet),
+ notInSet, checkGetItemNull, expectedSize);
+ }
+
+ @Override
+ protected boolean isFilteredOutItemNull() {
+ return false;
+ }
+
+ @Test
+ public void testGetType_existingProperty_typeReturned() {
+ BeanItemContainer<ClassName> container = getContainer();
+ Assert.assertEquals(
+ "Unexpected type is returned for property 'simpleName'",
+ String.class, container.getType("simpleName"));
+ }
+
+ @Test
+ public void testGetType_notExistingProperty_nullReturned() {
+ BeanItemContainer<ClassName> container = getContainer();
+ Assert.assertNull("Not null type is returned for property ''",
+ container.getType(""));
+ }
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(getContainer());
+ }
+
+ @Test
+ public void testFiltering() {
+ testContainerFiltering(getContainer());
+ }
+
+ @Test
+ public void testSorting() {
+ testContainerSorting(getContainer());
+ }
+
+ @Test
+ public void testSortingAndFiltering() {
+ testContainerSortingAndFiltering(getContainer());
+ }
+
+ // duplicated from parent class and modified - adding items to
+ // BeanItemContainer differs from other containers
+ @Test
+ public void testContainerOrdered() {
+ BeanItemContainer<String> container = new BeanItemContainer<String>(
+ String.class);
+
+ String id = "test1";
+
+ Item item = container.addBean(id);
+ assertNotNull(item);
+
+ assertEquals(id, container.firstItemId());
+ assertEquals(id, container.lastItemId());
+
+ // isFirstId
+ assertTrue(container.isFirstId(id));
+ assertTrue(container.isFirstId(container.firstItemId()));
+ // isLastId
+ assertTrue(container.isLastId(id));
+ assertTrue(container.isLastId(container.lastItemId()));
+
+ // Add a new item before the first
+ // addItemAfter
+ String newFirstId = "newFirst";
+ item = container.addItemAfter(null, newFirstId);
+ assertNotNull(item);
+ assertNotNull(container.getItem(newFirstId));
+
+ // isFirstId
+ assertTrue(container.isFirstId(newFirstId));
+ assertTrue(container.isFirstId(container.firstItemId()));
+ // isLastId
+ assertTrue(container.isLastId(id));
+ assertTrue(container.isLastId(container.lastItemId()));
+
+ // nextItemId
+ assertEquals(id, container.nextItemId(newFirstId));
+ assertNull(container.nextItemId(id));
+ assertNull(container.nextItemId("not-in-container"));
+
+ // prevItemId
+ assertEquals(newFirstId, container.prevItemId(id));
+ assertNull(container.prevItemId(newFirstId));
+ assertNull(container.prevItemId("not-in-container"));
+
+ // addItemAfter(Object)
+ String newSecondItemId = "newSecond";
+ item = container.addItemAfter(newFirstId, newSecondItemId);
+ // order is now: newFirstId, newSecondItemId, id
+ assertNotNull(item);
+ assertNotNull(container.getItem(newSecondItemId));
+ assertEquals(id, container.nextItemId(newSecondItemId));
+ assertEquals(newFirstId, container.prevItemId(newSecondItemId));
+
+ // addItemAfter(Object,Object)
+ String fourthId = "id of the fourth item";
+ Item fourth = container.addItemAfter(newFirstId, fourthId);
+ // order is now: newFirstId, fourthId, newSecondItemId, id
+ assertNotNull(fourth);
+ assertEquals(fourth, container.getItem(fourthId));
+ assertEquals(newSecondItemId, container.nextItemId(fourthId));
+ assertEquals(newFirstId, container.prevItemId(fourthId));
+
+ // addItemAfter(Object,Object)
+ Object fifthId = "fifth";
+ Item fifth = container.addItemAfter(null, fifthId);
+ // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id
+ assertNotNull(fifth);
+ assertEquals(fifth, container.getItem(fifthId));
+ assertEquals(newFirstId, container.nextItemId(fifthId));
+ assertNull(container.prevItemId(fifthId));
+
+ }
+
+ @Test
+ public void testContainerIndexed() {
+ testContainerIndexed(getContainer(), nameToBean.get(sampleData[2]), 2,
+ false, new ClassName("org.vaadin.test.Test", 8888), true);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testCollectionConstructors() {
+ List<ClassName> classNames = new ArrayList<ClassName>();
+ classNames.add(new ClassName("a.b.c.Def", 1));
+ classNames.add(new ClassName("a.b.c.Fed", 2));
+ classNames.add(new ClassName("b.c.d.Def", 3));
+
+ // note that this constructor is problematic, users should use the
+ // version that
+ // takes the bean class as a parameter
+ BeanItemContainer<ClassName> container = new BeanItemContainer<ClassName>(
+ classNames);
+
+ Assert.assertEquals(3, container.size());
+ Assert.assertEquals(classNames.get(0), container.firstItemId());
+ Assert.assertEquals(classNames.get(1), container.getIdByIndex(1));
+ Assert.assertEquals(classNames.get(2), container.lastItemId());
+
+ BeanItemContainer<ClassName> container2 = new BeanItemContainer<ClassName>(
+ ClassName.class, classNames);
+
+ Assert.assertEquals(3, container2.size());
+ Assert.assertEquals(classNames.get(0), container2.firstItemId());
+ Assert.assertEquals(classNames.get(1), container2.getIdByIndex(1));
+ Assert.assertEquals(classNames.get(2), container2.lastItemId());
+ }
+
+ // this only applies to the collection constructor with no type parameter
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEmptyCollectionConstructor() {
+ try {
+ new BeanItemContainer<ClassName>((Collection<ClassName>) null);
+ Assert.fail(
+ "Initializing BeanItemContainer from a null collection should not work!");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ try {
+ new BeanItemContainer<ClassName>(new ArrayList<ClassName>());
+ Assert.fail(
+ "Initializing BeanItemContainer from an empty collection should not work!");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testItemSetChangeListeners() {
+ BeanItemContainer<ClassName> container = getContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ ClassName cn1 = new ClassName("com.example.Test", 1111);
+ ClassName cn2 = new ClassName("com.example.Test2", 2222);
+
+ initializeContainer(container);
+ counter.reset();
+ container.addBean(cn1);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItem(cn1);
+ counter.assertOnce();
+ // no notification if already in container
+ container.addItem(cn1);
+ counter.assertNone();
+ container.addItem(cn2);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(null, cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.firstItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(container.firstItemId(), cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.getIdByIndex(1),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(container.lastItemId(), cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.lastItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(0, cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.firstItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(1, cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.getIdByIndex(1),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(container.size(), cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.lastItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.removeItem(nameToBean.get(sampleData[0]));
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ // no notification for removing a non-existing item
+ container.removeItem(cn1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.removeAllItems();
+ counter.assertOnce();
+ // already empty
+ container.removeAllItems();
+ counter.assertNone();
+
+ }
+
+ @Test
+ public void testItemSetChangeListenersFiltering() {
+ BeanItemContainer<ClassName> container = getContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ ClassName cn1 = new ClassName("com.example.Test", 1111);
+ ClassName cn2 = new ClassName("com.example.Test2", 2222);
+ ClassName other = new ClassName("com.example.Other", 3333);
+
+ // simply adding or removing container filters should cause event
+ // (content changes)
+
+ initializeContainer(container);
+ counter.reset();
+ container.addContainerFilter(SIMPLE_NAME, "a", true, false);
+ counter.assertOnce();
+ container.removeContainerFilters(SIMPLE_NAME);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addContainerFilter(SIMPLE_NAME, "a", true, false);
+ counter.assertOnce();
+ container.removeAllContainerFilters();
+ counter.assertOnce();
+
+ // perform operations while filtering container
+
+ initializeContainer(container);
+ counter.reset();
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false);
+ counter.assertOnce();
+
+ // passes filter
+ container.addBean(cn1);
+ counter.assertOnce();
+
+ // passes filter but already in the container
+ container.addBean(cn1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+
+ // passes filter
+ container.addItem(cn1);
+ counter.assertOnce();
+ // already in the container
+ container.addItem(cn1);
+ counter.assertNone();
+ container.addItem(cn2);
+ counter.assertOnce();
+ // does not pass filter
+ container.addItem(other);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(null, cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.firstItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(container.firstItemId(), cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.getIdByIndex(1),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(container.lastItemId(), cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.lastItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(0, cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.firstItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(1, cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.getIdByIndex(1),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(container.size(), cn1);
+ counter.assertOnce();
+ Assert.assertEquals("com.example.Test",
+ container.getContainerProperty(container.lastItemId(),
+ FULLY_QUALIFIED_NAME).getValue());
+
+ // does not pass filter
+ // note: testAddRemoveWhileFiltering() checks position for these after
+ // removing filter etc, here concentrating on listeners
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(null, other);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(container.firstItemId(), other);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(container.lastItemId(), other);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(0, other);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(1, other);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(container.size(), other);
+ counter.assertNone();
+
+ // passes filter
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItem(cn1);
+ counter.assertOnce();
+ container.removeItem(cn1);
+ counter.assertOnce();
+
+ // does not pass filter
+
+ initializeContainer(container);
+ counter.reset();
+ // not visible
+ container.removeItem(nameToBean.get(sampleData[0]));
+ counter.assertNone();
+
+ container.removeAllItems();
+ counter.assertOnce();
+ // no visible items
+ container.removeAllItems();
+ counter.assertNone();
+ }
+
+ @Test
+ public void testAddRemoveWhileFiltering() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+
+ Person john = new Person("John");
+ Person jane = new Person("Jane");
+ Person matthew = new Person("Matthew");
+
+ Person jack = new Person("Jack");
+ Person michael = new Person("Michael");
+ Person william = new Person("William");
+ Person julia = new Person("Julia");
+ Person george = new Person("George");
+ Person mark = new Person("Mark");
+
+ container.addBean(john);
+ container.addBean(jane);
+ container.addBean(matthew);
+
+ assertEquals(3, container.size());
+ // john, jane, matthew
+
+ container.addContainerFilter("name", "j", true, true);
+
+ assertEquals(2, container.size());
+ // john, jane, (matthew)
+
+ // add a bean that passes the filter
+ container.addBean(jack);
+ assertEquals(3, container.size());
+ assertEquals(jack, container.lastItemId());
+ // john, jane, (matthew), jack
+
+ // add beans that do not pass the filter
+ container.addBean(michael);
+ // john, jane, (matthew), jack, (michael)
+ container.addItemAfter(null, william);
+ // (william), john, jane, (matthew), jack, (michael)
+
+ // add after an item that is shown
+ container.addItemAfter(john, george);
+ // (william), john, (george), jane, (matthew), jack, (michael)
+ assertEquals(3, container.size());
+ assertEquals(john, container.firstItemId());
+
+ // add after an item that is not shown does nothing
+ container.addItemAfter(william, julia);
+ // (william), john, (george), jane, (matthew), jack, (michael)
+ assertEquals(3, container.size());
+ assertEquals(john, container.firstItemId());
+
+ container.addItemAt(1, julia);
+ // (william), john, julia, (george), jane, (matthew), jack, (michael)
+
+ container.addItemAt(2, mark);
+ // (william), john, julia, (mark), (george), jane, (matthew), jack,
+ // (michael)
+
+ container.removeItem(matthew);
+ // (william), john, julia, (mark), (george), jane, jack, (michael)
+
+ assertEquals(4, container.size());
+ assertEquals(jack, container.lastItemId());
+
+ container.removeContainerFilters("name");
+
+ assertEquals(8, container.size());
+ assertEquals(william, container.firstItemId());
+ assertEquals(john, container.nextItemId(william));
+ assertEquals(julia, container.nextItemId(john));
+ assertEquals(mark, container.nextItemId(julia));
+ assertEquals(george, container.nextItemId(mark));
+ assertEquals(jane, container.nextItemId(george));
+ assertEquals(jack, container.nextItemId(jane));
+ assertEquals(michael, container.lastItemId());
+ }
+
+ @Test
+ public void testRefilterOnPropertyModification() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+
+ Person john = new Person("John");
+ Person jane = new Person("Jane");
+ Person matthew = new Person("Matthew");
+
+ container.addBean(john);
+ container.addBean(jane);
+ container.addBean(matthew);
+
+ assertEquals(3, container.size());
+ // john, jane, matthew
+
+ container.addContainerFilter("name", "j", true, true);
+
+ assertEquals(2, container.size());
+ // john, jane, (matthew)
+
+ // #6053 currently, modification of an item that is not visible does not
+ // trigger refiltering - should it?
+ // matthew.setName("Julia");
+ // assertEquals(3, container.size());
+ // john, jane, julia
+
+ john.setName("Mark");
+ assertEquals(2, container.size());
+ // (mark), jane, julia
+
+ container.removeAllContainerFilters();
+
+ assertEquals(3, container.size());
+ }
+
+ @Test
+ public void testAddAll() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+
+ Person john = new Person("John");
+ Person jane = new Person("Jane");
+ Person matthew = new Person("Matthew");
+
+ container.addBean(john);
+ container.addBean(jane);
+ container.addBean(matthew);
+
+ assertEquals(3, container.size());
+ // john, jane, matthew
+
+ Person jack = new Person("Jack");
+ Person michael = new Person("Michael");
+
+ // addAll
+ container.addAll(Arrays.asList(jack, michael));
+ // john, jane, matthew, jack, michael
+
+ assertEquals(5, container.size());
+ assertEquals(jane, container.nextItemId(john));
+ assertEquals(matthew, container.nextItemId(jane));
+ assertEquals(jack, container.nextItemId(matthew));
+ assertEquals(michael, container.nextItemId(jack));
+ }
+
+ @Test
+ public void testUnsupportedMethods() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ container.addBean(new Person("John"));
+
+ try {
+ container.addItem();
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItemAfter(new Person("Jane"));
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addItemAt(0);
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ try {
+ container.addContainerProperty("lastName", String.class, "");
+ Assert.fail();
+ } catch (UnsupportedOperationException e) {
+ // should get exception
+ }
+
+ assertEquals(1, container.size());
+ }
+
+ @Test
+ public void testRemoveContainerProperty() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person john = new Person("John");
+ container.addBean(john);
+
+ Assert.assertEquals("John",
+ container.getContainerProperty(john, "name").getValue());
+ Assert.assertTrue(container.removeContainerProperty("name"));
+ Assert.assertNull(container.getContainerProperty(john, "name"));
+
+ Assert.assertNotNull(container.getItem(john));
+ // property removed also from item
+ Assert.assertNull(container.getItem(john).getItemProperty("name"));
+ }
+
+ @Test
+ public void testAddNullBean() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person john = new Person("John");
+ container.addBean(john);
+
+ assertNull(container.addItem(null));
+ assertNull(container.addItemAfter(null, null));
+ assertNull(container.addItemAfter(john, null));
+ assertNull(container.addItemAt(0, null));
+
+ assertEquals(1, container.size());
+ }
+
+ @Test
+ public void testBeanIdResolver() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person john = new Person("John");
+
+ assertSame(john, container.getBeanIdResolver().getIdForBean(john));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullBeanClass() {
+ new BeanItemContainer<Object>((Class<Object>) null);
+ }
+
+ @Test
+ public void testAddNestedContainerProperty() {
+ BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>(
+ NestedMethodPropertyTest.Person.class);
+
+ NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person(
+ "John",
+ new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", 20540));
+ container.addBean(john);
+
+ assertTrue(container.addNestedContainerProperty("address.street"));
+ assertEquals("Ruukinkatu 2-4", container
+ .getContainerProperty(john, "address.street").getValue());
+ }
+
+ @Test
+ public void testNestedContainerPropertyWithNullBean() {
+ BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>(
+ NestedMethodPropertyTest.Person.class);
+ NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person(
+ "John", null);
+ assertNotNull(container.addBean(john));
+ assertTrue(container
+ .addNestedContainerProperty("address.postalCodeObject"));
+ assertTrue(container.addNestedContainerProperty("address.street"));
+ // the nested properties should return null
+ assertNull(container.getContainerProperty(john, "address.street")
+ .getValue());
+ }
+
+ @Test
+ public void testItemAddedEvent() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ addListener.containerItemSetChange(EasyMock.isA(ItemAddEvent.class));
+ EasyMock.replay(addListener);
+
+ container.addItem(bean);
+
+ EasyMock.verify(addListener);
+ }
+
+ @Test
+ public void testItemAddedEvent_AddedItem() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ container.addItem(bean);
+
+ assertEquals(bean, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemAddedEvent_addItemAt_IndexOfAddedItem() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ container.addItem(bean);
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ container.addItemAt(1, new Person(""));
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemAddedEvent_addItemAfter_IndexOfAddedItem() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ container.addItem(bean);
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ container.addItemAfter(bean, new Person(""));
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemAddedEvent_amountOfAddedItems() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+ List<Person> beans = Arrays.asList(new Person("Jack"),
+ new Person("John"));
+
+ container.addAll(beans);
+
+ assertEquals(2, capturedEvent.getValue().getAddedItemsCount());
+ }
+
+ @Test
+ public void testItemAddedEvent_someItemsAreFiltered_amountOfAddedItemsIsReducedByAmountOfFilteredItems() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+ List<Person> beans = Arrays.asList(new Person("Jack"),
+ new Person("John"));
+ container.addFilter(new Compare.Equal("name", "John"));
+
+ container.addAll(beans);
+
+ assertEquals(1, capturedEvent.getValue().getAddedItemsCount());
+ }
+
+ @Test
+ public void testItemAddedEvent_someItemsAreFiltered_addedItemIsTheFirstVisibleItem() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+ List<Person> beans = Arrays.asList(new Person("Jack"), bean);
+ container.addFilter(new Compare.Equal("name", "John"));
+
+ container.addAll(beans);
+
+ assertEquals(bean, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemRemovedEvent() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ container.addItem(bean);
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ removeListener
+ .containerItemSetChange(EasyMock.isA(ItemRemoveEvent.class));
+ EasyMock.replay(removeListener);
+
+ container.removeItem(bean);
+
+ EasyMock.verify(removeListener);
+ }
+
+ @Test
+ public void testItemRemovedEvent_RemovedItem() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ Person bean = new Person("John");
+ container.addItem(bean);
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeItem(bean);
+
+ assertEquals(bean, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemRemovedEvent_indexOfRemovedItem() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ container.addItem(new Person("Jack"));
+ Person secondBean = new Person("John");
+ container.addItem(secondBean);
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeItem(secondBean);
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemRemovedEvent_amountOfRemovedItems() {
+ BeanItemContainer<Person> container = new BeanItemContainer<Person>(
+ Person.class);
+ container.addItem(new Person("Jack"));
+ container.addItem(new Person("John"));
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeAllItems();
+
+ assertEquals(2, capturedEvent.getValue().getRemovedItemsCount());
+ }
+
+ private Capture<ItemAddEvent> captureAddEvent(
+ ItemSetChangeListener addListener) {
+ Capture<ItemAddEvent> capturedEvent = new Capture<ItemAddEvent>();
+ addListener.containerItemSetChange(EasyMock.capture(capturedEvent));
+ return capturedEvent;
+ }
+
+ private Capture<ItemRemoveEvent> captureRemoveEvent(
+ ItemSetChangeListener removeListener) {
+ Capture<ItemRemoveEvent> capturedEvent = new Capture<ItemRemoveEvent>();
+ removeListener.containerItemSetChange(EasyMock.capture(capturedEvent));
+ return capturedEvent;
+ }
+
+ private ItemSetChangeListener createListenerMockFor(
+ BeanItemContainer<Person> container) {
+ ItemSetChangeListener listener = EasyMock
+ .createNiceMock(ItemSetChangeListener.class);
+ container.addItemSetChangeListener(listener);
+ return listener;
+ }
+
+ @Test
+ public void testAddNestedContainerBeanBeforeData() {
+ BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>(
+ NestedMethodPropertyTest.Person.class);
+
+ container.addNestedContainerBean("address");
+
+ assertTrue(
+ container.getContainerPropertyIds().contains("address.street"));
+
+ NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person(
+ "John", new Address("streetname", 12345));
+ container.addBean(john);
+
+ assertTrue(container.getItem(john).getItemPropertyIds()
+ .contains("address.street"));
+ assertEquals("streetname", container.getItem(john)
+ .getItemProperty("address.street").getValue());
+
+ }
+
+ @Test
+ public void testAddNestedContainerBeanAfterData() {
+ BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>(
+ NestedMethodPropertyTest.Person.class);
+
+ NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person(
+ "John", new Address("streetname", 12345));
+ container.addBean(john);
+
+ container.addNestedContainerBean("address");
+
+ assertTrue(
+ container.getContainerPropertyIds().contains("address.street"));
+ assertTrue(container.getItem(john).getItemPropertyIds()
+ .contains("address.street"));
+ assertEquals("streetname", container.getItem(john)
+ .getItemProperty("address.street").getValue());
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java
new file mode 100644
index 0000000000..1bbe74818c
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java
@@ -0,0 +1,389 @@
+package com.vaadin.data.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Property;
+
+/**
+ * Test BeanItem specific features.
+ *
+ * Only public API is tested, not the methods with package visibility.
+ *
+ * See also {@link PropertySetItemTest}, which tests the base class.
+ */
+public class BeanItemTest {
+
+ @SuppressWarnings("unused")
+ protected static class MySuperClass {
+ private int superPrivate = 1;
+ private int superPrivate2 = 2;
+ protected double superProtected = 3.0;
+ private double superProtected2 = 4.0;
+ public boolean superPublic = true;
+ private boolean superPublic2 = true;
+
+ public int getSuperPrivate() {
+ return superPrivate;
+ }
+
+ public void setSuperPrivate(int superPrivate) {
+ this.superPrivate = superPrivate;
+ }
+
+ public double getSuperProtected() {
+ return superProtected;
+ }
+
+ public void setSuperProtected(double superProtected) {
+ this.superProtected = superProtected;
+ }
+
+ public boolean isSuperPublic() {
+ return superPublic;
+ }
+
+ public void setSuperPublic(boolean superPublic) {
+ this.superPublic = superPublic;
+ }
+
+ }
+
+ protected static class MyClass extends MySuperClass {
+ private String name;
+ public int value = 123;
+
+ public MyClass(String name) {
+ this.name = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setNoField(String name) {
+ }
+
+ public String getNoField() {
+ return "no field backing this setter";
+ }
+
+ public String getName2() {
+ return name;
+ }
+ }
+
+ protected static class MyClass2 extends MyClass {
+ public MyClass2(String name) {
+ super(name);
+ }
+
+ @Override
+ public void setName(String name) {
+ super.setName(name + "2");
+ }
+
+ @Override
+ public String getName() {
+ return super.getName() + "2";
+ }
+
+ @Override
+ public String getName2() {
+ return super.getName();
+ }
+
+ public void setName2(String name) {
+ super.setName(name);
+ }
+ }
+
+ protected static interface MySuperInterface {
+ public int getSuper1();
+
+ public void setSuper1(int i);
+
+ public int getOverride();
+ }
+
+ protected static interface MySuperInterface2 {
+ public int getSuper2();
+ }
+
+ protected static class Generic<T> {
+
+ public T getProperty() {
+ return null;
+ }
+
+ public void setProperty(T t) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ protected static class SubClass extends Generic<String> {
+
+ @Override
+ // Has a bridged method
+ public String getProperty() {
+ return "";
+ }
+
+ @Override
+ // Has a bridged method
+ public void setProperty(String t) {
+ }
+ }
+
+ protected static interface MySubInterface
+ extends MySuperInterface, MySuperInterface2 {
+ public int getSub();
+
+ public void setSub(int i);
+
+ @Override
+ public int getOverride();
+
+ public void setOverride(int i);
+ }
+
+ @Test
+ public void testGetProperties() {
+ BeanItem<MySuperClass> item = new BeanItem<MySuperClass>(
+ new MySuperClass());
+
+ Collection<?> itemPropertyIds = item.getItemPropertyIds();
+ Assert.assertEquals(3, itemPropertyIds.size());
+ Assert.assertTrue(itemPropertyIds.contains("superPrivate"));
+ Assert.assertTrue(itemPropertyIds.contains("superProtected"));
+ Assert.assertTrue(itemPropertyIds.contains("superPublic"));
+ }
+
+ @Test
+ public void testGetSuperClassProperties() {
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"));
+
+ Collection<?> itemPropertyIds = item.getItemPropertyIds();
+ Assert.assertEquals(6, itemPropertyIds.size());
+ Assert.assertTrue(itemPropertyIds.contains("superPrivate"));
+ Assert.assertTrue(itemPropertyIds.contains("superProtected"));
+ Assert.assertTrue(itemPropertyIds.contains("superPublic"));
+ Assert.assertTrue(itemPropertyIds.contains("name"));
+ Assert.assertTrue(itemPropertyIds.contains("noField"));
+ Assert.assertTrue(itemPropertyIds.contains("name2"));
+ }
+
+ @Test
+ public void testOverridingProperties() {
+ BeanItem<MyClass2> item = new BeanItem<MyClass2>(new MyClass2("bean2"));
+
+ Collection<?> itemPropertyIds = item.getItemPropertyIds();
+ Assert.assertEquals(6, itemPropertyIds.size());
+
+ Assert.assertTrue(MyClass2.class.equals(item.getBean().getClass()));
+
+ // check that name2 accessed via MyClass2, not MyClass
+ Assert.assertFalse(item.getItemProperty("name2").isReadOnly());
+ }
+
+ @Test
+ public void testGetInterfaceProperties() throws SecurityException,
+ NoSuchMethodException, IllegalArgumentException,
+ IllegalAccessException, InvocationTargetException {
+ Method method = BeanItem.class
+ .getDeclaredMethod("getPropertyDescriptors", Class.class);
+ method.setAccessible(true);
+ LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method
+ .invoke(null, MySuperInterface.class);
+
+ Assert.assertEquals(2, propertyDescriptors.size());
+ Assert.assertTrue(propertyDescriptors.containsKey("super1"));
+ Assert.assertTrue(propertyDescriptors.containsKey("override"));
+
+ MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors
+ .get("override").createProperty(getClass());
+ Assert.assertTrue(property.isReadOnly());
+ }
+
+ @Test
+ public void testGetSuperInterfaceProperties() throws SecurityException,
+ NoSuchMethodException, IllegalArgumentException,
+ IllegalAccessException, InvocationTargetException {
+ Method method = BeanItem.class
+ .getDeclaredMethod("getPropertyDescriptors", Class.class);
+ method.setAccessible(true);
+ LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method
+ .invoke(null, MySubInterface.class);
+
+ Assert.assertEquals(4, propertyDescriptors.size());
+ Assert.assertTrue(propertyDescriptors.containsKey("sub"));
+ Assert.assertTrue(propertyDescriptors.containsKey("super1"));
+ Assert.assertTrue(propertyDescriptors.containsKey("super2"));
+ Assert.assertTrue(propertyDescriptors.containsKey("override"));
+
+ MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors
+ .get("override").createProperty(getClass());
+ Assert.assertFalse(property.isReadOnly());
+ }
+
+ @Test
+ public void testPropertyExplicitOrder() {
+ Collection<String> ids = new ArrayList<String>();
+ ids.add("name");
+ ids.add("superPublic");
+ ids.add("name2");
+ ids.add("noField");
+
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"),
+ ids);
+
+ Iterator<?> it = item.getItemPropertyIds().iterator();
+ Assert.assertEquals("name", it.next());
+ Assert.assertEquals("superPublic", it.next());
+ Assert.assertEquals("name2", it.next());
+ Assert.assertEquals("noField", it.next());
+ Assert.assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testPropertyExplicitOrder2() {
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"),
+ new String[] { "name", "superPublic", "name2", "noField" });
+
+ Iterator<?> it = item.getItemPropertyIds().iterator();
+ Assert.assertEquals("name", it.next());
+ Assert.assertEquals("superPublic", it.next());
+ Assert.assertEquals("name2", it.next());
+ Assert.assertEquals("noField", it.next());
+ Assert.assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testPropertyBadPropertyName() {
+ Collection<String> ids = new ArrayList<String>();
+ ids.add("name3");
+ ids.add("name");
+
+ // currently silently ignores non-existent properties
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"),
+ ids);
+
+ Iterator<?> it = item.getItemPropertyIds().iterator();
+ Assert.assertEquals("name", it.next());
+ Assert.assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testRemoveProperty() {
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"));
+
+ Collection<?> itemPropertyIds = item.getItemPropertyIds();
+ Assert.assertEquals(6, itemPropertyIds.size());
+
+ item.removeItemProperty("name2");
+ Assert.assertEquals(5, itemPropertyIds.size());
+ Assert.assertFalse(itemPropertyIds.contains("name2"));
+ }
+
+ @Test
+ public void testRemoveSuperProperty() {
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"));
+
+ Collection<?> itemPropertyIds = item.getItemPropertyIds();
+ Assert.assertEquals(6, itemPropertyIds.size());
+
+ item.removeItemProperty("superPrivate");
+ Assert.assertEquals(5, itemPropertyIds.size());
+ Assert.assertFalse(itemPropertyIds.contains("superPrivate"));
+ }
+
+ @Test
+ public void testPropertyTypes() {
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"));
+
+ Assert.assertTrue(Integer.class
+ .equals(item.getItemProperty("superPrivate").getType()));
+ Assert.assertTrue(Double.class
+ .equals(item.getItemProperty("superProtected").getType()));
+ Assert.assertTrue(Boolean.class
+ .equals(item.getItemProperty("superPublic").getType()));
+ Assert.assertTrue(
+ String.class.equals(item.getItemProperty("name").getType()));
+ }
+
+ @Test
+ public void testPropertyReadOnly() {
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"));
+
+ Assert.assertFalse(item.getItemProperty("name").isReadOnly());
+ Assert.assertTrue(item.getItemProperty("name2").isReadOnly());
+ }
+
+ @Test
+ public void testCustomProperties() throws Exception {
+ LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>> propertyDescriptors = new LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>>();
+ propertyDescriptors.put("myname",
+ new MethodPropertyDescriptor<BeanItemTest.MyClass>("myname",
+ MyClass.class,
+ MyClass.class.getDeclaredMethod("getName"),
+ MyClass.class.getDeclaredMethod("setName",
+ String.class)));
+ MyClass instance = new MyClass("bean1");
+ Constructor<BeanItem> constructor = BeanItem.class
+ .getDeclaredConstructor(Object.class, Map.class);
+ constructor.setAccessible(true);
+ BeanItem<MyClass> item = constructor.newInstance(instance,
+ propertyDescriptors);
+
+ Assert.assertEquals(1, item.getItemPropertyIds().size());
+ Assert.assertEquals("bean1", item.getItemProperty("myname").getValue());
+ }
+
+ @Test
+ public void testAddRemoveProperty() throws Exception {
+ MethodPropertyDescriptor<BeanItemTest.MyClass> pd = new MethodPropertyDescriptor<BeanItemTest.MyClass>(
+ "myname", MyClass.class,
+ MyClass.class.getDeclaredMethod("getName"),
+ MyClass.class.getDeclaredMethod("setName", String.class));
+
+ BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"));
+
+ Assert.assertEquals(6, item.getItemPropertyIds().size());
+ Assert.assertEquals(null, item.getItemProperty("myname"));
+
+ item.addItemProperty("myname", pd.createProperty(item.getBean()));
+ Assert.assertEquals(7, item.getItemPropertyIds().size());
+ Assert.assertEquals("bean1", item.getItemProperty("myname").getValue());
+ item.removeItemProperty("myname");
+ Assert.assertEquals(6, item.getItemPropertyIds().size());
+ Assert.assertEquals(null, item.getItemProperty("myname"));
+ }
+
+ @Test
+ public void testOverridenGenericMethods() {
+ BeanItem<SubClass> item = new BeanItem<SubClass>(new SubClass());
+
+ Property<?> property = item.getItemProperty("property");
+ Assert.assertEquals("Unexpected class for property type", String.class,
+ property.getType());
+
+ Assert.assertEquals("Unexpected property value", "",
+ property.getValue());
+
+ // Should not be exception
+ property.setValue(null);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java
new file mode 100644
index 0000000000..e41f751bfd
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java
@@ -0,0 +1,26 @@
+package com.vaadin.data.util;
+
+import org.junit.Test;
+
+public class ContainerHierarchicalWrapperTest
+ extends AbstractHierarchicalContainerTestBase {
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(
+ new ContainerHierarchicalWrapper(new IndexedContainer()));
+ }
+
+ @Test
+ public void testHierarchicalContainer() {
+ testHierarchicalContainer(
+ new ContainerHierarchicalWrapper(new IndexedContainer()));
+ }
+
+ @Test
+ public void testRemoveSubtree() {
+ testRemoveHierarchicalWrapperSubtree(
+ new ContainerHierarchicalWrapper(new IndexedContainer()));
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java
new file mode 100644
index 0000000000..c3a8b2c4f9
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java
@@ -0,0 +1,107 @@
+package com.vaadin.data.util;
+
+import java.util.Collection;
+
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+
+public class ContainerOrderedWrapperTest extends AbstractContainerTestBase {
+
+ // This class is needed to get an implementation of container
+ // which is not an implementation of Ordered interface.
+ private class NotOrderedContainer implements Container {
+
+ private IndexedContainer container;
+
+ public NotOrderedContainer() {
+ container = new IndexedContainer();
+ }
+
+ @Override
+ public Item getItem(Object itemId) {
+ return container.getItem(itemId);
+ }
+
+ @Override
+ public Collection<?> getContainerPropertyIds() {
+ return container.getContainerPropertyIds();
+ }
+
+ @Override
+ public Collection<?> getItemIds() {
+ return container.getItemIds();
+ }
+
+ @Override
+ public Property getContainerProperty(Object itemId, Object propertyId) {
+ return container.getContainerProperty(itemId, propertyId);
+ }
+
+ @Override
+ public Class<?> getType(Object propertyId) {
+ return container.getType(propertyId);
+ }
+
+ @Override
+ public int size() {
+ return container.size();
+ }
+
+ @Override
+ public boolean containsId(Object itemId) {
+ return container.containsId(itemId);
+ }
+
+ @Override
+ public Item addItem(Object itemId)
+ throws UnsupportedOperationException {
+ return container.addItem(itemId);
+ }
+
+ @Override
+ public Object addItem() throws UnsupportedOperationException {
+ return container.addItem();
+ }
+
+ @Override
+ public boolean removeItem(Object itemId)
+ throws UnsupportedOperationException {
+ return container.removeItem(itemId);
+ }
+
+ @Override
+ public boolean addContainerProperty(Object propertyId, Class<?> type,
+ Object defaultValue) throws UnsupportedOperationException {
+ return container.addContainerProperty(propertyId, type,
+ defaultValue);
+ }
+
+ @Override
+ public boolean removeContainerProperty(Object propertyId)
+ throws UnsupportedOperationException {
+ return container.removeContainerProperty(propertyId);
+ }
+
+ @Override
+ public boolean removeAllItems() throws UnsupportedOperationException {
+ return container.removeAllItems();
+ }
+
+ }
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(
+ new ContainerOrderedWrapper(new NotOrderedContainer()));
+ }
+
+ @Test
+ public void testOrdered() {
+ testContainerOrdered(
+ new ContainerOrderedWrapper(new NotOrderedContainer()));
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java
new file mode 100644
index 0000000000..58cb2b1d27
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2016 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.util;
+
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.ui.Table;
+
+public class ContainerSizeAssertTest {
+
+ @Test(expected = AssertionError.class)
+ public void testNegativeSizeAssert() {
+ Table table = createAttachedTable();
+
+ table.setContainerDataSource(createNegativeSizeContainer());
+ }
+
+ @Test
+ public void testZeroSizeNoAssert() {
+ Table table = createAttachedTable();
+
+ table.setContainerDataSource(new IndexedContainer());
+ }
+
+ private Container createNegativeSizeContainer() {
+ return new IndexedContainer() {
+ @Override
+ public int size() {
+ return -1;
+ }
+ };
+ }
+
+ private Table createAttachedTable() {
+ return new Table() {
+ private boolean initialized = true;
+
+ @Override
+ public boolean isAttached() {
+ // This returns false until the super constructor has finished
+ return initialized;
+ }
+ };
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java
new file mode 100644
index 0000000000..1c4dc1de5e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java
@@ -0,0 +1,222 @@
+package com.vaadin.data.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.tests.util.TestUtil;
+
+public class ContainerSortingTest {
+
+ private static final String ITEM_DATA_MINUS2_NULL = "Data -2 null";
+ private static final String ITEM_DATA_MINUS2 = "Data -2";
+ private static final String ITEM_DATA_MINUS1 = "Data -1";
+ private static final String ITEM_DATA_MINUS1_NULL = "Data -1 null";
+ private static final String ITEM_ANOTHER_NULL = "Another null";
+ private static final String ITEM_STRING_2 = "String 2";
+ private static final String ITEM_STRING_NULL2 = "String null";
+ private static final String ITEM_STRING_1 = "String 1";
+
+ private static final String PROPERTY_INTEGER_NULL2 = "integer-null";
+ private static final String PROPERTY_INTEGER_NOT_NULL = "integer-not-null";
+ private static final String PROPERTY_STRING_NULL = "string-null";
+ private static final String PROPERTY_STRING_ID = "string-not-null";
+
+ @Test
+ public void testEmptyFilteredIndexedContainer() {
+ IndexedContainer ic = new IndexedContainer();
+
+ addProperties(ic);
+ populate(ic);
+
+ ic.addContainerFilter(PROPERTY_STRING_ID, "aasdfasdfasdf", true, false);
+ ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true });
+
+ }
+
+ @Test
+ public void testFilteredIndexedContainer() {
+ IndexedContainer ic = new IndexedContainer();
+
+ addProperties(ic);
+ populate(ic);
+
+ ic.addContainerFilter(PROPERTY_STRING_ID, "a", true, false);
+ ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true });
+ verifyOrder(ic,
+ new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1,
+ ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2,
+ ITEM_DATA_MINUS2_NULL, });
+ }
+
+ @Test
+ public void testIndexedContainer() {
+ IndexedContainer ic = new IndexedContainer();
+
+ addProperties(ic);
+ populate(ic);
+
+ ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true });
+ verifyOrder(ic, new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1,
+ ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL,
+ ITEM_STRING_1, ITEM_STRING_2, ITEM_STRING_NULL2 });
+
+ ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL,
+ PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID },
+ new boolean[] { true, false, true });
+ verifyOrder(ic, new String[] { ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL,
+ ITEM_DATA_MINUS1, ITEM_DATA_MINUS1_NULL, ITEM_ANOTHER_NULL,
+ ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 });
+
+ ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL,
+ PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID },
+ new boolean[] { true, true, true });
+ verifyOrder(ic, new String[] { ITEM_DATA_MINUS2_NULL, ITEM_DATA_MINUS2,
+ ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS1, ITEM_ANOTHER_NULL,
+ ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 });
+
+ }
+
+ @Test
+ public void testHierarchicalContainer() {
+ HierarchicalContainer hc = new HierarchicalContainer();
+ populateContainer(hc);
+ hc.sort(new Object[] { "name" }, new boolean[] { true });
+ verifyOrder(hc,
+ new String[] { "Audi", "C++", "Call of Duty", "Cars", "English",
+ "Fallout", "Finnish", "Ford", "Games", "Java",
+ "Might and Magic", "Natural languages", "PHP",
+ "Programming languages", "Python", "Red Alert",
+ "Swedish", "Toyota", "Volvo" });
+ TestUtil.assertArrays(hc.rootItemIds().toArray(),
+ new Integer[] { nameToId.get("Cars"), nameToId.get("Games"),
+ nameToId.get("Natural languages"),
+ nameToId.get("Programming languages") });
+ TestUtil.assertArrays(hc.getChildren(nameToId.get("Games")).toArray(),
+ new Integer[] { nameToId.get("Call of Duty"),
+ nameToId.get("Fallout"),
+ nameToId.get("Might and Magic"),
+ nameToId.get("Red Alert") });
+ }
+
+ private static void populateContainer(HierarchicalContainer container) {
+ container.addContainerProperty("name", String.class, null);
+
+ addItem(container, "Games", null);
+ addItem(container, "Call of Duty", "Games");
+ addItem(container, "Might and Magic", "Games");
+ addItem(container, "Fallout", "Games");
+ addItem(container, "Red Alert", "Games");
+
+ addItem(container, "Cars", null);
+ addItem(container, "Toyota", "Cars");
+ addItem(container, "Volvo", "Cars");
+ addItem(container, "Audi", "Cars");
+ addItem(container, "Ford", "Cars");
+
+ addItem(container, "Natural languages", null);
+ addItem(container, "Swedish", "Natural languages");
+ addItem(container, "English", "Natural languages");
+ addItem(container, "Finnish", "Natural languages");
+
+ addItem(container, "Programming languages", null);
+ addItem(container, "C++", "Programming languages");
+ addItem(container, "PHP", "Programming languages");
+ addItem(container, "Java", "Programming languages");
+ addItem(container, "Python", "Programming languages");
+
+ }
+
+ private static int index = 0;
+ private static Map<String, Integer> nameToId = new HashMap<String, Integer>();
+ private static Map<Integer, String> idToName = new HashMap<Integer, String>();
+
+ public static void addItem(IndexedContainer container, String string,
+ String parent) {
+ nameToId.put(string, index);
+ idToName.put(index, string);
+
+ Item item = container.addItem(index);
+ item.getItemProperty("name").setValue(string);
+
+ if (parent != null && container instanceof HierarchicalContainer) {
+ ((HierarchicalContainer) container).setParent(index,
+ nameToId.get(parent));
+ }
+
+ index++;
+ }
+
+ private void verifyOrder(Container.Sortable ic, Object[] idOrder) {
+ int size = ic.size();
+ Object[] actual = new Object[size];
+ Iterator<?> i = ic.getItemIds().iterator();
+ int index = 0;
+ while (i.hasNext()) {
+ Object o = i.next();
+ if (o.getClass() == Integer.class
+ && idOrder[index].getClass() == String.class) {
+ o = idToName.get(o);
+ }
+ actual[index++] = o;
+ }
+
+ TestUtil.assertArrays(actual, idOrder);
+
+ }
+
+ private void populate(IndexedContainer ic) {
+ addItem(ic, ITEM_STRING_1, ITEM_STRING_1, 1, 1);
+ addItem(ic, ITEM_STRING_NULL2, null, 0, null);
+ addItem(ic, ITEM_STRING_2, ITEM_STRING_2, 2, 2);
+ addItem(ic, ITEM_ANOTHER_NULL, null, 0, null);
+ addItem(ic, ITEM_DATA_MINUS1, ITEM_DATA_MINUS1, -1, -1);
+ addItem(ic, ITEM_DATA_MINUS1_NULL, null, -1, null);
+ addItem(ic, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2, -2, -2);
+ addItem(ic, ITEM_DATA_MINUS2_NULL, null, -2, null);
+ }
+
+ private Item addItem(Container ic, String id, String string_null,
+ int integer, Integer integer_null) {
+ Item i = ic.addItem(id);
+ i.getItemProperty(PROPERTY_STRING_ID).setValue(id);
+ i.getItemProperty(PROPERTY_STRING_NULL).setValue(string_null);
+ i.getItemProperty(PROPERTY_INTEGER_NOT_NULL).setValue(integer);
+ i.getItemProperty(PROPERTY_INTEGER_NULL2).setValue(integer_null);
+
+ return i;
+ }
+
+ private void addProperties(IndexedContainer ic) {
+ ic.addContainerProperty("id", String.class, null);
+ ic.addContainerProperty(PROPERTY_STRING_ID, String.class, "");
+ ic.addContainerProperty(PROPERTY_STRING_NULL, String.class, null);
+ ic.addContainerProperty(PROPERTY_INTEGER_NULL2, Integer.class, null);
+ ic.addContainerProperty(PROPERTY_INTEGER_NOT_NULL, Integer.class, 0);
+ ic.addContainerProperty("comparable-null", Integer.class, 0);
+ }
+
+ public class MyObject implements Comparable<MyObject> {
+ private String data;
+
+ @Override
+ public int compareTo(MyObject o) {
+ if (o == null) {
+ return 1;
+ }
+
+ if (o.data == null) {
+ return data == null ? 0 : 1;
+ } else if (data == null) {
+ return -1;
+ } else {
+ return data.compareTo(o.data);
+ }
+ }
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java
new file mode 100644
index 0000000000..992b265702
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java
@@ -0,0 +1,16 @@
+package com.vaadin.data.util;
+
+import java.io.File;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FileSystemContainerTest {
+
+ @Test
+ public void nonExistingDirectory() {
+ FilesystemContainer fsc = new FilesystemContainer(
+ new File("/non/existing"));
+ Assert.assertTrue(fsc.getItemIds().isEmpty());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java
new file mode 100644
index 0000000000..11335314f0
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java
@@ -0,0 +1,596 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Indexed.ItemAddEvent;
+import com.vaadin.data.Container.Indexed.ItemRemoveEvent;
+import com.vaadin.data.Container.ItemSetChangeListener;
+import com.vaadin.data.Container.ItemSetChangeNotifier;
+import com.vaadin.data.Item;
+import com.vaadin.data.util.filter.SimpleStringFilter;
+
+public class GeneratedPropertyContainerBasicTest
+ extends AbstractInMemoryContainerTestBase {
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(createContainer());
+ }
+
+ private GeneratedPropertyContainer createContainer() {
+ return new GeneratedPropertyContainer(new IndexedContainer());
+ }
+
+ @Test
+ public void testFiltering() {
+ testContainerFiltering(createContainer());
+ }
+
+ @Test
+ public void testSorting() {
+ testContainerSorting(createContainer());
+ }
+
+ @Test
+ public void testSortingAndFiltering() {
+ testContainerSortingAndFiltering(createContainer());
+ }
+
+ @Test
+ public void testContainerOrdered() {
+ testContainerOrdered(createContainer());
+ }
+
+ @Test
+ public void testContainerIndexed() {
+ testContainerIndexed(createContainer(), sampleData[2], 2, true,
+ "newItemId", true);
+ }
+
+ @Test
+ public void testItemSetChangeListeners() {
+ GeneratedPropertyContainer container = createContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ String id1 = "id1";
+ String id2 = "id2";
+ String id3 = "id3";
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItem();
+ counter.assertOnce();
+ container.addItem(id1);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(0);
+ counter.assertOnce();
+ container.addItemAt(0, id1);
+ counter.assertOnce();
+ container.addItemAt(0, id2);
+ counter.assertOnce();
+ container.addItemAt(container.size(), id3);
+ counter.assertOnce();
+ // no notification if already in container
+ container.addItemAt(0, id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(null);
+ counter.assertOnce();
+ container.addItemAfter(null, id1);
+ counter.assertOnce();
+ container.addItemAfter(id1);
+ counter.assertOnce();
+ container.addItemAfter(id1, id2);
+ counter.assertOnce();
+ container.addItemAfter(container.firstItemId());
+ counter.assertOnce();
+ container.addItemAfter(container.lastItemId());
+ counter.assertOnce();
+ container.addItemAfter(container.lastItemId(), id3);
+ counter.assertOnce();
+ // no notification if already in container
+ container.addItemAfter(0, id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.removeItem(sampleData[0]);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ // no notification for removing a non-existing item
+ container.removeItem(id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.removeAllItems();
+ counter.assertOnce();
+ // already empty
+ container.removeAllItems();
+ counter.assertNone();
+
+ }
+
+ @Test
+ public void testAddRemoveContainerFilter() {
+ GeneratedPropertyContainer container = createContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ // simply adding or removing container filters should cause events
+ // (content changes)
+
+ initializeContainer(container);
+ counter.reset();
+ SimpleStringFilter filter = new SimpleStringFilter(SIMPLE_NAME, "a",
+ true, false);
+ container.addContainerFilter(filter);
+ counter.assertOnce();
+ container.removeContainerFilter(filter);
+ counter.assertOnce();
+ container.addContainerFilter(
+ new SimpleStringFilter(SIMPLE_NAME, "a", true, false));
+ counter.assertOnce();
+ container.removeAllContainerFilters();
+ counter.assertOnce();
+ }
+
+ // TODO other tests should check positions after removing filter etc,
+ // here concentrating on listeners
+ @Test
+ public void testItemSetChangeListenersFiltering() {
+ Container.Indexed container = createContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ ((GeneratedPropertyContainer) container).addListener(counter);
+
+ counter.reset();
+ ((Container.Filterable) container)
+ .addContainerFilter(new SimpleStringFilter(FULLY_QUALIFIED_NAME,
+ "Test", true, false));
+ // no real change, so no notification required
+ counter.assertNone();
+
+ String id1 = "com.example.Test1";
+ String id2 = "com.example.Test2";
+ String id3 = "com.example.Other";
+
+ // perform operations while filtering container
+
+ Item item;
+
+ initializeContainer(container);
+ counter.reset();
+ // passes filter
+ item = container.addItem(id1);
+ // no event if filtered out
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ // passes filter but already in the container
+ item = container.addItem(id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ // passes filter after change
+ item = container.addItemAt(0, id1);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ item = container.addItemAt(container.size(), id2);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2);
+ counter.assertOnce();
+ // passes filter but already in the container
+ item = container.addItemAt(0, id1);
+ counter.assertNone();
+ item = container.addItemAt(container.size(), id2);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ // passes filter
+ item = container.addItemAfter(null, id1);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ item = container.addItemAfter(container.lastItemId(), id2);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2);
+ counter.assertOnce();
+ // passes filter but already in the container
+ item = container.addItemAfter(null, id1);
+ counter.assertNone();
+ item = container.addItemAfter(container.lastItemId(), id2);
+ counter.assertNone();
+
+ // does not pass filter
+
+ // TODO implement rest
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAfter(null, id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAfter(container.firstItemId(), id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAfter(container.lastItemId(), id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAt(0, id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAt(1, id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAt(container.size(), id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ // passes filter
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItem(id1);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ container.removeItem(id1);
+ counter.assertOnce();
+ // already removed
+ container.removeItem(id1);
+ counter.assertNone();
+
+ item = container.addItem(id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+ // not visible
+ container.removeItem(id3);
+ counter.assertNone();
+
+ // remove all
+
+ initializeContainer(container);
+ item = container.addItem(id1);
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.reset();
+ container.removeAllItems();
+ counter.assertOnce();
+ // no visible items
+ container.removeAllItems();
+ counter.assertNone();
+ }
+
+ @Test
+ public void testItemAdd_idSequence() {
+ GeneratedPropertyContainer container = createContainer();
+ 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);
+ }
+
+ @Test
+ public void testItemAddRemove_idSequence() {
+ GeneratedPropertyContainer container = createContainer();
+ 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);
+ }
+
+ @Test
+ public void testItemAddedEvent() {
+ GeneratedPropertyContainer container = createContainer();
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ addListener.containerItemSetChange(EasyMock.isA(ItemAddEvent.class));
+ EasyMock.replay(addListener);
+
+ container.addItem();
+
+ EasyMock.verify(addListener);
+ }
+
+ @Test
+ public void testItemAddedEvent_AddedItem() {
+ GeneratedPropertyContainer container = createContainer();
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ Object itemId = container.addItem();
+
+ assertEquals(itemId, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemAddedEvent_IndexOfAddedItem() {
+ GeneratedPropertyContainer container = createContainer();
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ container.addItem();
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ Object itemId = container.addItemAt(1);
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemRemovedEvent() {
+ GeneratedPropertyContainer container = createContainer();
+ Object itemId = container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ removeListener
+ .containerItemSetChange(EasyMock.isA(ItemRemoveEvent.class));
+ EasyMock.replay(removeListener);
+
+ container.removeItem(itemId);
+
+ EasyMock.verify(removeListener);
+ }
+
+ @Test
+ public void testItemRemovedEvent_RemovedItem() {
+ GeneratedPropertyContainer container = createContainer();
+ Object itemId = container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeItem(itemId);
+
+ assertEquals(itemId, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemRemovedEvent_indexOfRemovedItem() {
+ GeneratedPropertyContainer container = createContainer();
+ container.addItem();
+ Object secondItemId = container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeItem(secondItemId);
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemRemovedEvent_amountOfRemovedItems() {
+ GeneratedPropertyContainer container = createContainer();
+ container.addItem();
+ container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeAllItems();
+
+ assertEquals(2, capturedEvent.getValue().getRemovedItemsCount());
+ }
+
+ private Capture<ItemAddEvent> captureAddEvent(
+ ItemSetChangeListener addListener) {
+ Capture<ItemAddEvent> capturedEvent = new Capture<ItemAddEvent>();
+ addListener.containerItemSetChange(EasyMock.capture(capturedEvent));
+ return capturedEvent;
+ }
+
+ private Capture<ItemRemoveEvent> captureRemoveEvent(
+ ItemSetChangeListener removeListener) {
+ Capture<ItemRemoveEvent> capturedEvent = new Capture<ItemRemoveEvent>();
+ removeListener.containerItemSetChange(EasyMock.capture(capturedEvent));
+ return capturedEvent;
+ }
+
+ private ItemSetChangeListener createListenerMockFor(
+ ItemSetChangeNotifier container) {
+ ItemSetChangeListener listener = EasyMock
+ .createNiceMock(ItemSetChangeListener.class);
+ container.addItemSetChangeListener(listener);
+ return listener;
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeIndexOutOfBounds() {
+ GeneratedPropertyContainer ic = createContainer();
+ try {
+ ic.getItemIds(-1, 10);
+ fail("Container returned items starting from index -1, something very wrong here!");
+ } catch (IndexOutOfBoundsException e) {
+ // This is expected...
+ } catch (Exception e) {
+ // Should not happen!
+ fail("Container threw unspecified exception when fetching a range of items and the range started from -1");
+ }
+
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeIndexOutOfBounds2() {
+ GeneratedPropertyContainer ic = createContainer();
+ ic.addItem(new Object());
+ try {
+ ic.getItemIds(2, 1);
+ fail("Container returned items starting from index -1, something very wrong here!");
+ } catch (IndexOutOfBoundsException e) {
+ // This is expected...
+ } catch (Exception e) {
+ // Should not happen!
+ fail("Container threw unspecified exception when fetching a out of bounds range of items");
+ }
+
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeZeroRange() {
+ GeneratedPropertyContainer ic = createContainer();
+ ic.addItem(new Object());
+ try {
+ List<Object> itemIds = (List<Object>) ic.getItemIds(1, 0);
+
+ assertTrue(
+ "Container returned actual values when asking for 0 items...",
+ itemIds.isEmpty());
+ } catch (Exception e) {
+ // Should not happen!
+ fail("Container threw unspecified exception when fetching 0 items...");
+ }
+
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeNegativeRange() {
+ GeneratedPropertyContainer ic = createContainer();
+ ic.addItem(new Object());
+ try {
+ List<Object> itemIds = (List<Object>) ic.getItemIds(1, -1);
+
+ assertTrue(
+ "Container returned actual values when asking for -1 items...",
+ itemIds.isEmpty());
+ } catch (IllegalArgumentException e) {
+ // this is expected
+
+ } catch (Exception e) {
+ // Should not happen!
+ fail("Container threw unspecified exception when fetching -1 items...");
+ }
+
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeIndexOutOfBoundsDueToSizeChange() {
+ GeneratedPropertyContainer ic = createContainer();
+ ic.addItem(new Object());
+ Assert.assertEquals(
+ "Container returned too many items when the range was >> container size",
+ 1, ic.getItemIds(0, 10).size());
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeBaseCase() {
+ GeneratedPropertyContainer ic = createContainer();
+ String object1 = new String("Obj1");
+ String object2 = new String("Obj2");
+ String object3 = new String("Obj3");
+ String object4 = new String("Obj4");
+ String object5 = new String("Obj5");
+
+ ic.addItem(object1);
+ ic.addItem(object2);
+ ic.addItem(object3);
+ ic.addItem(object4);
+ ic.addItem(object5);
+
+ try {
+ List<Object> itemIds = (List<Object>) ic.getItemIds(1, 2);
+
+ assertTrue(itemIds.contains(object2));
+ assertTrue(itemIds.contains(object3));
+ assertEquals(2, itemIds.size());
+
+ } catch (Exception e) {
+ // Should not happen!
+ fail("Container threw exception when fetching a range of items ");
+ }
+ }
+
+ // test getting non-existing property (#10445)
+ @Test
+ public void testNonExistingProperty() {
+ Container ic = createContainer();
+ String object1 = new String("Obj1");
+ ic.addItem(object1);
+ assertNull(ic.getContainerProperty(object1, "xyz"));
+ }
+
+ // test getting null property id (#10445)
+ @Test
+ public void testNullPropertyId() {
+ Container ic = createContainer();
+ String object1 = new String("Obj1");
+ ic.addItem(object1);
+ assertNull(ic.getContainerProperty(object1, null));
+ }
+
+ @Override
+ protected void initializeContainer(Container container) {
+ if (container instanceof GeneratedPropertyContainer) {
+ super.initializeContainer(((GeneratedPropertyContainer) container)
+ .getWrappedContainer());
+ } else {
+ super.initializeContainer(container);
+ }
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java
new file mode 100644
index 0000000000..1e34567439
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2000-2016 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container.Filter;
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.data.Container.ItemSetChangeEvent;
+import com.vaadin.data.Container.ItemSetChangeListener;
+import com.vaadin.data.Container.PropertySetChangeEvent;
+import com.vaadin.data.Container.PropertySetChangeListener;
+import com.vaadin.data.Item;
+import com.vaadin.data.sort.SortOrder;
+import com.vaadin.data.util.GeneratedPropertyContainer.GeneratedPropertyItem;
+import com.vaadin.data.util.filter.Compare;
+import com.vaadin.data.util.filter.UnsupportedFilterException;
+
+public class GeneratedPropertyContainerTest {
+
+ GeneratedPropertyContainer container;
+ Indexed wrappedContainer;
+ private static double MILES_CONVERSION = 0.6214d;
+
+ private class GeneratedPropertyListener
+ implements PropertySetChangeListener {
+
+ private int callCount = 0;
+
+ public int getCallCount() {
+ return callCount;
+ }
+
+ @Override
+ public void containerPropertySetChange(PropertySetChangeEvent event) {
+ ++callCount;
+ assertEquals(
+ "Container for event was not GeneratedPropertyContainer",
+ event.getContainer(), container);
+ }
+ }
+
+ private class GeneratedItemSetListener implements ItemSetChangeListener {
+
+ private int callCount = 0;
+
+ public int getCallCount() {
+ return callCount;
+ }
+
+ @Override
+ public void containerItemSetChange(ItemSetChangeEvent event) {
+ ++callCount;
+ assertEquals(
+ "Container for event was not GeneratedPropertyContainer",
+ event.getContainer(), container);
+ }
+ }
+
+ @Before
+ public void setUp() {
+ container = new GeneratedPropertyContainer(createContainer());
+ }
+
+ @Test
+ public void testSimpleGeneratedProperty() {
+ container.addGeneratedProperty("hello",
+ new PropertyValueGenerator<String>() {
+
+ @Override
+ public String getValue(Item item, Object itemId,
+ Object propertyId) {
+ return "Hello World!";
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+ });
+
+ Object itemId = container.addItem();
+ assertEquals("Expected value not in item.",
+ container.getItem(itemId).getItemProperty("hello").getValue(),
+ "Hello World!");
+ }
+
+ @Test
+ public void testSortableProperties() {
+ container.addGeneratedProperty("baz",
+ new PropertyValueGenerator<String>() {
+
+ @Override
+ public String getValue(Item item, Object itemId,
+ Object propertyId) {
+ return item.getItemProperty("foo").getValue() + " "
+ + item.getItemProperty("bar").getValue();
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+
+ @Override
+ public SortOrder[] getSortProperties(SortOrder order) {
+ SortOrder[] sortOrder = new SortOrder[1];
+ sortOrder[0] = new SortOrder("bar",
+ order.getDirection());
+ return sortOrder;
+ }
+ });
+
+ container.sort(new Object[] { "baz" }, new boolean[] { true });
+ assertEquals("foo 0", container.getItem(container.getIdByIndex(0))
+ .getItemProperty("baz").getValue());
+
+ container.sort(new Object[] { "baz" }, new boolean[] { false });
+ assertEquals("foo 10", container.getItem(container.getIdByIndex(0))
+ .getItemProperty("baz").getValue());
+ }
+
+ @Test
+ public void testOverrideSortableProperties() {
+
+ assertTrue(container.getSortableContainerPropertyIds().contains("bar"));
+
+ container.addGeneratedProperty("bar",
+ new PropertyValueGenerator<String>() {
+
+ @Override
+ public String getValue(Item item, Object itemId,
+ Object propertyId) {
+ return item.getItemProperty("foo").getValue() + " "
+ + item.getItemProperty("bar").getValue();
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+ });
+
+ assertFalse(
+ container.getSortableContainerPropertyIds().contains("bar"));
+ }
+
+ @Test
+ public void testFilterByMiles() {
+ container.addGeneratedProperty("miles",
+ new PropertyValueGenerator<Double>() {
+
+ @Override
+ public Double getValue(Item item, Object itemId,
+ Object propertyId) {
+ return (Double) item.getItemProperty("km").getValue()
+ * MILES_CONVERSION;
+ }
+
+ @Override
+ public Class<Double> getType() {
+ return Double.class;
+ }
+
+ @Override
+ public Filter modifyFilter(Filter filter)
+ throws UnsupportedFilterException {
+ if (filter instanceof Compare.LessOrEqual) {
+ Double value = (Double) ((Compare.LessOrEqual) filter)
+ .getValue();
+ value = value / MILES_CONVERSION;
+ return new Compare.LessOrEqual("km", value);
+ }
+ return super.modifyFilter(filter);
+ }
+ });
+
+ for (Object itemId : container.getItemIds()) {
+ Item item = container.getItem(itemId);
+ Double km = (Double) item.getItemProperty("km").getValue();
+ Double miles = (Double) item.getItemProperty("miles").getValue();
+ assertTrue(miles.equals(km * MILES_CONVERSION));
+ }
+
+ Filter filter = new Compare.LessOrEqual("miles", MILES_CONVERSION);
+ container.addContainerFilter(filter);
+ for (Object itemId : container.getItemIds()) {
+ Item item = container.getItem(itemId);
+ assertTrue("Item did not pass original filter.",
+ filter.passesFilter(itemId, item));
+ }
+
+ assertTrue(container.getContainerFilters().contains(filter));
+ container.removeContainerFilter(filter);
+ assertFalse(container.getContainerFilters().contains(filter));
+
+ boolean allPass = true;
+ for (Object itemId : container.getItemIds()) {
+ Item item = container.getItem(itemId);
+ if (!filter.passesFilter(itemId, item)) {
+ allPass = false;
+ }
+ }
+
+ if (allPass) {
+ fail("Removing filter did not introduce any previous filtered items");
+ }
+ }
+
+ @Test
+ public void testPropertySetChangeNotifier() {
+ GeneratedPropertyListener listener = new GeneratedPropertyListener();
+ GeneratedPropertyListener removedListener = new GeneratedPropertyListener();
+ container.addPropertySetChangeListener(listener);
+ container.addPropertySetChangeListener(removedListener);
+
+ container.addGeneratedProperty("foo",
+ new PropertyValueGenerator<String>() {
+
+ @Override
+ public String getValue(Item item, Object itemId,
+ Object propertyId) {
+ return "";
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+ });
+
+ // Adding property to wrapped container should cause an event
+ wrappedContainer.addContainerProperty("baz", String.class, "");
+ container.removePropertySetChangeListener(removedListener);
+ container.removeGeneratedProperty("foo");
+
+ assertEquals("Listener was not called correctly.", 3,
+ listener.getCallCount());
+ assertEquals("Removed listener was not called correctly.", 2,
+ removedListener.getCallCount());
+ }
+
+ @Test
+ public void testItemSetChangeNotifier() {
+ GeneratedItemSetListener listener = new GeneratedItemSetListener();
+ container.addItemSetChangeListener(listener);
+
+ container.sort(new Object[] { "foo" }, new boolean[] { true });
+ container.sort(new Object[] { "foo" }, new boolean[] { false });
+
+ assertEquals("Listener was not called correctly.", 2,
+ listener.getCallCount());
+
+ }
+
+ @Test
+ public void testRemoveProperty() {
+ container.removeContainerProperty("foo");
+ assertFalse("Container contained removed property",
+ container.getContainerPropertyIds().contains("foo"));
+ assertTrue("Wrapped container did not contain removed property",
+ wrappedContainer.getContainerPropertyIds().contains("foo"));
+
+ assertFalse(container.getItem(container.firstItemId())
+ .getItemPropertyIds().contains("foo"));
+
+ container.addContainerProperty("foo", null, null);
+ assertTrue("Container did not contain returned property",
+ container.getContainerPropertyIds().contains("foo"));
+ }
+
+ @Test
+ public void testGetWrappedItem() {
+ Object itemId = wrappedContainer.getItemIds().iterator().next();
+ Item wrappedItem = wrappedContainer.getItem(itemId);
+ GeneratedPropertyItem generatedPropertyItem = (GeneratedPropertyItem) container
+ .getItem(itemId);
+ assertEquals(wrappedItem, generatedPropertyItem.getWrappedItem());
+ }
+
+ private Indexed createContainer() {
+ wrappedContainer = new IndexedContainer();
+ wrappedContainer.addContainerProperty("foo", String.class, "foo");
+ wrappedContainer.addContainerProperty("bar", Integer.class, 0);
+ // km contains double values from 0.0 to 2.0
+ wrappedContainer.addContainerProperty("km", Double.class, 0);
+
+ for (int i = 0; i <= 10; ++i) {
+ Object itemId = wrappedContainer.addItem();
+ Item item = wrappedContainer.getItem(itemId);
+ item.getItemProperty("foo").setValue("foo");
+ item.getItemProperty("bar").setValue(i);
+ item.getItemProperty("km").setValue(i / 5.0d);
+ }
+
+ return wrappedContainer;
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java
new file mode 100644
index 0000000000..54984f07ad
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java
@@ -0,0 +1,33 @@
+package com.vaadin.data.util;
+
+import org.junit.Test;
+
+public class HierarchicalContainerOrderedWrapperTest
+ extends AbstractHierarchicalContainerTestBase {
+
+ private HierarchicalContainerOrderedWrapper createContainer() {
+ return new HierarchicalContainerOrderedWrapper(
+ new ContainerHierarchicalWrapper(new IndexedContainer()));
+ }
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(createContainer());
+ }
+
+ @Test
+ public void testHierarchicalContainer() {
+ testHierarchicalContainer(createContainer());
+ }
+
+ @Test
+ public void testContainerOrdered() {
+ testContainerOrdered(createContainer());
+ }
+
+ @Test
+ public void testRemoveSubtree() {
+ testRemoveHierarchicalWrapperSubtree(createContainer());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java
new file mode 100644
index 0000000000..7ab20ca3dd
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java
@@ -0,0 +1,286 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+import com.vaadin.data.Container.Filter;
+import com.vaadin.data.Item;
+
+public class HierarchicalContainerTest
+ extends AbstractHierarchicalContainerTestBase {
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(new HierarchicalContainer());
+ }
+
+ @Test
+ public void testFiltering() {
+ testContainerFiltering(new HierarchicalContainer());
+ }
+
+ @Test
+ public void testSorting() {
+ testContainerSorting(new HierarchicalContainer());
+ }
+
+ @Test
+ public void testOrdered() {
+ testContainerOrdered(new HierarchicalContainer());
+ }
+
+ @Test
+ public void testHierarchicalSorting() {
+ testHierarchicalSorting(new HierarchicalContainer());
+ }
+
+ @Test
+ public void testSortingAndFiltering() {
+ testContainerSortingAndFiltering(new HierarchicalContainer());
+ }
+
+ @Test
+ public void testRemovingItemsFromFilteredContainer() {
+ HierarchicalContainer container = new HierarchicalContainer();
+ initializeContainer(container);
+ container.setIncludeParentsWhenFiltering(true);
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false);
+ Object p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertEquals("com.vaadin.ui", p1);
+
+ container.removeItem("com.vaadin.ui.TabSheet");
+ // Parent for the removed item must be null because the item is no
+ // longer in the container
+ p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertNull("Parent should be null, is " + p1, p1);
+
+ container.removeAllItems();
+ p1 = container.getParent("com.vaadin.terminal.gwt.client.Focusable");
+ assertNull("Parent should be null, is " + p1, p1);
+
+ }
+
+ @Test
+ public void testParentWhenRemovingFilterFromContainer() {
+ HierarchicalContainer container = new HierarchicalContainer();
+ initializeContainer(container);
+ container.setIncludeParentsWhenFiltering(true);
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false);
+ Object p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertEquals("com.vaadin.ui", p1);
+ p1 = container
+ .getParent("com.vaadin.terminal.gwt.client.ui.VPopupCalendar");
+ assertNull(p1);
+ container.removeAllContainerFilters();
+ p1 = container
+ .getParent("com.vaadin.terminal.gwt.client.ui.VPopupCalendar");
+ assertEquals("com.vaadin.terminal.gwt.client.ui", p1);
+
+ }
+
+ @Test
+ public void testChangeParentInFilteredContainer() {
+ HierarchicalContainer container = new HierarchicalContainer();
+ initializeContainer(container);
+ container.setIncludeParentsWhenFiltering(true);
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "Tab", false, false);
+
+ // Change parent of filtered item
+ Object p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertEquals("com.vaadin.ui", p1);
+ container.setParent("com.vaadin.ui.TabSheet", "com.vaadin");
+ p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertEquals("com.vaadin", p1);
+ container.setParent("com.vaadin.ui.TabSheet", "com");
+ p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertEquals("com", p1);
+ container.setParent("com.vaadin.ui.TabSheet", null);
+ p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertNull(p1);
+
+ // root -> non-root
+ container.setParent("com.vaadin.ui.TabSheet", "com");
+ p1 = container.getParent("com.vaadin.ui.TabSheet");
+ assertEquals("com", p1);
+
+ }
+
+ @Test
+ public void testHierarchicalFilteringWithParents() {
+ HierarchicalContainer container = new HierarchicalContainer();
+ initializeContainer(container);
+ container.setIncludeParentsWhenFiltering(true);
+
+ // Filter by "contains ab"
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false);
+
+ // 20 items match the filters and the have 8 parents that should also be
+ // included
+ // only one root "com" should exist
+ // filtered
+ int expectedSize = 29;
+ int expectedRoots = 1;
+
+ validateHierarchicalContainer(container, "com",
+ "com.vaadin.ui.TabSheet",
+ "com.vaadin.terminal.gwt.client.Focusable", "blah", true,
+ expectedSize, expectedRoots, true);
+
+ // only include .gwt.client classes
+ container.removeAllContainerFilters();
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.",
+ false, false);
+
+ int packages = 6;
+ int classes = 112;
+
+ expectedSize = packages + classes;
+ expectedRoots = 1;
+
+ validateHierarchicalContainer(container, "com",
+ "com.vaadin.terminal.gwt.client.WidgetSet",
+ "com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical", "blah",
+ true, expectedSize, expectedRoots, true);
+
+ // Additionally remove all without 'm' in the simple name.
+ container.addContainerFilter(SIMPLE_NAME, "m", false, false);
+
+ expectedSize = 7 + 18;
+ expectedRoots = 1;
+
+ validateHierarchicalContainer(container, "com",
+ "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility",
+ "com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer",
+ "blah", true, expectedSize, expectedRoots, true);
+
+ }
+
+ @Test
+ public void testRemoveLastChild() {
+ HierarchicalContainer c = new HierarchicalContainer();
+
+ c.addItem("root");
+ assertEquals(false, c.hasChildren("root"));
+
+ c.addItem("child");
+ c.setParent("child", "root");
+ assertEquals(true, c.hasChildren("root"));
+
+ c.removeItem("child");
+ assertFalse(c.containsId("child"));
+ assertNull(c.getChildren("root"));
+ assertNull(c.getChildren("child"));
+ assertFalse(c.hasChildren("child"));
+ assertFalse(c.hasChildren("root"));
+ }
+
+ @Test
+ public void testRemoveLastChildFromFiltered() {
+ HierarchicalContainer c = new HierarchicalContainer();
+
+ c.addItem("root");
+ assertEquals(false, c.hasChildren("root"));
+
+ c.addItem("child");
+ c.setParent("child", "root");
+ assertEquals(true, c.hasChildren("root"));
+
+ // Dummy filter that does not remove any items
+ c.addContainerFilter(new Filter() {
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ return true;
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return true;
+ }
+ });
+ c.removeItem("child");
+
+ assertFalse(c.containsId("child"));
+ assertNull(c.getChildren("root"));
+ assertNull(c.getChildren("child"));
+ assertFalse(c.hasChildren("child"));
+ assertFalse(c.hasChildren("root"));
+ }
+
+ @Test
+ public void testHierarchicalFilteringWithoutParents() {
+ HierarchicalContainer container = new HierarchicalContainer();
+
+ initializeContainer(container);
+ container.setIncludeParentsWhenFiltering(false);
+
+ // Filter by "contains ab"
+ container.addContainerFilter(SIMPLE_NAME, "ab", false, false);
+
+ // 20 items match the filter.
+ // com.vaadin.data.BufferedValidatable
+ // com.vaadin.data.Validatable
+ // com.vaadin.terminal.gwt.client.Focusable
+ // com.vaadin.terminal.gwt.client.Paintable
+ // com.vaadin.terminal.gwt.client.ui.Table
+ // com.vaadin.terminal.gwt.client.ui.VLabel
+ // com.vaadin.terminal.gwt.client.ui.VScrollTable
+ // com.vaadin.terminal.gwt.client.ui.VTablePaging
+ // com.vaadin.terminal.gwt.client.ui.VTabsheet
+ // com.vaadin.terminal.gwt.client.ui.VTabsheetBase
+ // com.vaadin.terminal.gwt.client.ui.VTabsheetPanel
+ // com.vaadin.server.ChangeVariablesErrorEvent
+ // com.vaadin.server.Paintable
+ // com.vaadin.server.Scrollable
+ // com.vaadin.server.Sizeable
+ // com.vaadin.server.VariableOwner
+ // com.vaadin.ui.Label
+ // com.vaadin.ui.Table
+ // com.vaadin.ui.TableFieldFactory
+ // com.vaadin.ui.TabSheet
+ // all become roots.
+ int expectedSize = 20;
+ int expectedRoots = 20;
+
+ validateHierarchicalContainer(container,
+ "com.vaadin.data.BufferedValidatable", "com.vaadin.ui.TabSheet",
+ "com.vaadin.terminal.gwt.client.ui.VTabsheetBase", "blah", true,
+ expectedSize, expectedRoots, false);
+
+ // only include .gwt.client classes
+ container.removeAllContainerFilters();
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.",
+ false, false);
+
+ int packages = 3;
+ int classes = 110;
+
+ expectedSize = packages + classes;
+ expectedRoots = 35 + 1; // com.vaadin.terminal.gwt.client.ui +
+ // com.vaadin.terminal.gwt.client.*
+
+ // Sorting is case insensitive
+ validateHierarchicalContainer(container,
+ "com.vaadin.terminal.gwt.client.ApplicationConfiguration",
+ "com.vaadin.terminal.gwt.client.WidgetSet",
+ "com.vaadin.terminal.gwt.client.ui.VOptionGroup", "blah", true,
+ expectedSize, expectedRoots, false);
+
+ // Additionally remove all without 'P' in the simple name.
+ container.addContainerFilter(SIMPLE_NAME, "P", false, false);
+
+ expectedSize = 13;
+ expectedRoots = expectedSize;
+
+ validateHierarchicalContainer(container,
+ "com.vaadin.terminal.gwt.client.Paintable",
+ "com.vaadin.terminal.gwt.client.ui.VTabsheetPanel",
+ "com.vaadin.terminal.gwt.client.ui.VPopupCalendar", "blah",
+ true, expectedSize, expectedRoots, false);
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java
new file mode 100644
index 0000000000..b19a425518
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java
@@ -0,0 +1,533 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Container.Indexed.ItemAddEvent;
+import com.vaadin.data.Container.Indexed.ItemRemoveEvent;
+import com.vaadin.data.Container.ItemSetChangeListener;
+import com.vaadin.data.Item;
+
+public class IndexedContainerTest extends AbstractInMemoryContainerTestBase {
+
+ @Test
+ public void testBasicOperations() {
+ testBasicContainerOperations(new IndexedContainer());
+ }
+
+ @Test
+ public void testFiltering() {
+ testContainerFiltering(new IndexedContainer());
+ }
+
+ @Test
+ public void testSorting() {
+ testContainerSorting(new IndexedContainer());
+ }
+
+ @Test
+ public void testSortingAndFiltering() {
+ testContainerSortingAndFiltering(new IndexedContainer());
+ }
+
+ @Test
+ public void testContainerOrdered() {
+ testContainerOrdered(new IndexedContainer());
+ }
+
+ @Test
+ public void testContainerIndexed() {
+ testContainerIndexed(new IndexedContainer(), sampleData[2], 2, true,
+ "newItemId", true);
+ }
+
+ @Test
+ public void testItemSetChangeListeners() {
+ IndexedContainer container = new IndexedContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ String id1 = "id1";
+ String id2 = "id2";
+ String id3 = "id3";
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItem();
+ counter.assertOnce();
+ container.addItem(id1);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAt(0);
+ counter.assertOnce();
+ container.addItemAt(0, id1);
+ counter.assertOnce();
+ container.addItemAt(0, id2);
+ counter.assertOnce();
+ container.addItemAt(container.size(), id3);
+ counter.assertOnce();
+ // no notification if already in container
+ container.addItemAt(0, id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.addItemAfter(null);
+ counter.assertOnce();
+ container.addItemAfter(null, id1);
+ counter.assertOnce();
+ container.addItemAfter(id1);
+ counter.assertOnce();
+ container.addItemAfter(id1, id2);
+ counter.assertOnce();
+ container.addItemAfter(container.firstItemId());
+ counter.assertOnce();
+ container.addItemAfter(container.lastItemId());
+ counter.assertOnce();
+ container.addItemAfter(container.lastItemId(), id3);
+ counter.assertOnce();
+ // no notification if already in container
+ container.addItemAfter(0, id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.removeItem(sampleData[0]);
+ counter.assertOnce();
+
+ initializeContainer(container);
+ counter.reset();
+ // no notification for removing a non-existing item
+ container.removeItem(id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ container.removeAllItems();
+ counter.assertOnce();
+ // already empty
+ container.removeAllItems();
+ counter.assertNone();
+
+ }
+
+ @Test
+ public void testAddRemoveContainerFilter() {
+ IndexedContainer container = new IndexedContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ // simply adding or removing container filters should cause events
+ // (content changes)
+
+ initializeContainer(container);
+ counter.reset();
+ container.addContainerFilter(SIMPLE_NAME, "a", true, false);
+ counter.assertOnce();
+ container.removeContainerFilters(SIMPLE_NAME);
+ counter.assertOnce();
+ container.addContainerFilter(SIMPLE_NAME, "a", true, false);
+ counter.assertOnce();
+ container.removeAllContainerFilters();
+ counter.assertOnce();
+ }
+
+ // TODO other tests should check positions after removing filter etc,
+ // here concentrating on listeners
+ @Test
+ public void testItemSetChangeListenersFiltering() {
+ IndexedContainer container = new IndexedContainer();
+ ItemSetChangeCounter counter = new ItemSetChangeCounter();
+ container.addListener(counter);
+
+ counter.reset();
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false);
+ // no real change, so no notification required
+ counter.assertNone();
+
+ String id1 = "com.example.Test1";
+ String id2 = "com.example.Test2";
+ String id3 = "com.example.Other";
+
+ // perform operations while filtering container
+
+ Item item;
+
+ initializeContainer(container);
+ counter.reset();
+ // passes filter
+ item = container.addItem(id1);
+ // no event if filtered out
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ // passes filter but already in the container
+ item = container.addItem(id1);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ // passes filter after change
+ item = container.addItemAt(0, id1);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ item = container.addItemAt(container.size(), id2);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2);
+ counter.assertOnce();
+ // passes filter but already in the container
+ item = container.addItemAt(0, id1);
+ counter.assertNone();
+ item = container.addItemAt(container.size(), id2);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ // passes filter
+ item = container.addItemAfter(null, id1);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ item = container.addItemAfter(container.lastItemId(), id2);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2);
+ counter.assertOnce();
+ // passes filter but already in the container
+ item = container.addItemAfter(null, id1);
+ counter.assertNone();
+ item = container.addItemAfter(container.lastItemId(), id2);
+ counter.assertNone();
+
+ // does not pass filter
+
+ // TODO implement rest
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAfter(null, id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAfter(container.firstItemId(), id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAfter(container.lastItemId(), id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAt(0, id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAt(1, id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItemAt(container.size(), id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+
+ // passes filter
+
+ initializeContainer(container);
+ counter.reset();
+ item = container.addItem(id1);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.assertOnce();
+ container.removeItem(id1);
+ counter.assertOnce();
+ // already removed
+ container.removeItem(id1);
+ counter.assertNone();
+
+ item = container.addItem(id3);
+ counter.assertNone();
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3);
+ counter.assertNone();
+ // not visible
+ container.removeItem(id3);
+ counter.assertNone();
+
+ // remove all
+
+ initializeContainer(container);
+ item = container.addItem(id1);
+ item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1);
+ counter.reset();
+ container.removeAllItems();
+ counter.assertOnce();
+ // no visible items
+ container.removeAllItems();
+ counter.assertNone();
+ }
+
+ @Test
+ 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);
+ }
+
+ @Test
+ 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);
+ }
+
+ @Test
+ public void testItemAddedEvent() {
+ IndexedContainer container = new IndexedContainer();
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ addListener.containerItemSetChange(EasyMock.isA(ItemAddEvent.class));
+ EasyMock.replay(addListener);
+
+ container.addItem();
+
+ EasyMock.verify(addListener);
+ }
+
+ @Test
+ public void testItemAddedEvent_AddedItem() {
+ IndexedContainer container = new IndexedContainer();
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ Object itemId = container.addItem();
+
+ assertEquals(itemId, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemAddedEvent_IndexOfAddedItem() {
+ IndexedContainer container = new IndexedContainer();
+ ItemSetChangeListener addListener = createListenerMockFor(container);
+ container.addItem();
+ Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener);
+ EasyMock.replay(addListener);
+
+ Object itemId = container.addItemAt(1);
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemRemovedEvent() {
+ IndexedContainer container = new IndexedContainer();
+ Object itemId = container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ removeListener
+ .containerItemSetChange(EasyMock.isA(ItemRemoveEvent.class));
+ EasyMock.replay(removeListener);
+
+ container.removeItem(itemId);
+
+ EasyMock.verify(removeListener);
+ }
+
+ @Test
+ public void testItemRemovedEvent_RemovedItem() {
+ IndexedContainer container = new IndexedContainer();
+ Object itemId = container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeItem(itemId);
+
+ assertEquals(itemId, capturedEvent.getValue().getFirstItemId());
+ }
+
+ @Test
+ public void testItemRemovedEvent_indexOfRemovedItem() {
+ IndexedContainer container = new IndexedContainer();
+ container.addItem();
+ Object secondItemId = container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeItem(secondItemId);
+
+ assertEquals(1, capturedEvent.getValue().getFirstIndex());
+ }
+
+ @Test
+ public void testItemRemovedEvent_amountOfRemovedItems() {
+ IndexedContainer container = new IndexedContainer();
+ container.addItem();
+ container.addItem();
+ ItemSetChangeListener removeListener = createListenerMockFor(container);
+ Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent(
+ removeListener);
+ EasyMock.replay(removeListener);
+
+ container.removeAllItems();
+
+ assertEquals(2, capturedEvent.getValue().getRemovedItemsCount());
+ }
+
+ private Capture<ItemAddEvent> captureAddEvent(
+ ItemSetChangeListener addListener) {
+ Capture<ItemAddEvent> capturedEvent = new Capture<ItemAddEvent>();
+ addListener.containerItemSetChange(EasyMock.capture(capturedEvent));
+ return capturedEvent;
+ }
+
+ private Capture<ItemRemoveEvent> captureRemoveEvent(
+ ItemSetChangeListener removeListener) {
+ Capture<ItemRemoveEvent> capturedEvent = new Capture<ItemRemoveEvent>();
+ removeListener.containerItemSetChange(EasyMock.capture(capturedEvent));
+ return capturedEvent;
+ }
+
+ private ItemSetChangeListener createListenerMockFor(
+ IndexedContainer container) {
+ ItemSetChangeListener listener = EasyMock
+ .createNiceMock(ItemSetChangeListener.class);
+ container.addItemSetChangeListener(listener);
+ return listener;
+ }
+
+ // Ticket 8028
+ @Test(expected = IndexOutOfBoundsException.class)
+ public void testGetItemIdsRangeIndexOutOfBounds() {
+ IndexedContainer ic = new IndexedContainer();
+ ic.getItemIds(-1, 10);
+ }
+
+ // Ticket 8028
+ @Test(expected = IndexOutOfBoundsException.class)
+ public void testGetItemIdsRangeIndexOutOfBounds2() {
+ IndexedContainer ic = new IndexedContainer();
+ ic.addItem(new Object());
+ ic.getItemIds(2, 1);
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeZeroRange() {
+ IndexedContainer ic = new IndexedContainer();
+ ic.addItem(new Object());
+ List<Object> itemIds = ic.getItemIds(1, 0);
+
+ assertTrue(
+ "Container returned actual values when asking for 0 items...",
+ itemIds.isEmpty());
+ }
+
+ // Ticket 8028
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetItemIdsRangeNegativeRange() {
+ IndexedContainer ic = new IndexedContainer();
+ ic.addItem(new Object());
+ List<Object> itemIds = ic.getItemIds(1, -1);
+
+ assertTrue(
+ "Container returned actual values when asking for -1 items...",
+ itemIds.isEmpty());
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeIndexOutOfBoundsDueToSizeChange() {
+ IndexedContainer ic = new IndexedContainer();
+ ic.addItem(new Object());
+ Assert.assertEquals(
+ "Container returned too many items when the range was >> container size",
+ 1, ic.getItemIds(0, 10).size());
+ }
+
+ // Ticket 8028
+ @Test
+ public void testGetItemIdsRangeBaseCase() {
+ IndexedContainer ic = new IndexedContainer();
+ String object1 = new String("Obj1");
+ String object2 = new String("Obj2");
+ String object3 = new String("Obj3");
+ String object4 = new String("Obj4");
+ String object5 = new String("Obj5");
+
+ ic.addItem(object1);
+ ic.addItem(object2);
+ ic.addItem(object3);
+ ic.addItem(object4);
+ ic.addItem(object5);
+
+ List<Object> itemIds = ic.getItemIds(1, 2);
+
+ assertTrue(itemIds.contains(object2));
+ assertTrue(itemIds.contains(object3));
+ assertEquals(2, itemIds.size());
+ }
+
+ // test getting non-existing property (#10445)
+ @Test
+ public void testNonExistingProperty() {
+ IndexedContainer ic = new IndexedContainer();
+ String object1 = new String("Obj1");
+ ic.addItem(object1);
+ assertNull(ic.getContainerProperty(object1, "xyz"));
+ }
+
+ // test getting null property id (#10445)
+ @Test
+ public void testNullPropertyId() {
+ IndexedContainer ic = new IndexedContainer();
+ String object1 = new String("Obj1");
+ ic.addItem(object1);
+ assertNull(ic.getContainerProperty(object1, null));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java
new file mode 100644
index 0000000000..6776021c24
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2016 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.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test for MethodProperty: don't allocate unnecessary Object arrays.
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public class MethodPropertyMemoryConsumptionTest {
+
+ @Test
+ public void testSetArguments()
+ throws NoSuchFieldException, SecurityException,
+ IllegalArgumentException, IllegalAccessException {
+ TestBean bean = new TestBean();
+ TestMethodProperty<String> property = new TestMethodProperty<String>(
+ bean, "name");
+ Object[] getArgs = property.getGetArgs();
+ Object[] setArgs = property.getSetArgs();
+
+ Field getArgsField = TestMethodProperty.class
+ .getDeclaredField("getArgs");
+ getArgsField.setAccessible(true);
+
+ Field setArgsField = TestMethodProperty.class
+ .getDeclaredField("setArgs");
+ setArgsField.setAccessible(true);
+
+ Assert.assertSame(
+ "setArguments method sets non-default instance"
+ + " of empty Object array for getArgs",
+ getArgsField.get(property), getArgs);
+
+ Assert.assertSame(
+ "setArguments method sets non-default instance"
+ + " of empty Object array for setArgs",
+ setArgsField.get(property), setArgs);
+ }
+
+ @Test
+ public void testDefaultCtor() {
+ TestBean bean = new TestBean();
+ TestMethodProperty<String> property = new TestMethodProperty<String>(
+ bean, "name");
+
+ Object[] getArgs = property.getGetArgs();
+ Object[] setArgs = property.getSetArgs();
+
+ TestBean otherBean = new TestBean();
+ TestMethodProperty<String> otherProperty = new TestMethodProperty<String>(
+ otherBean, "name");
+ Assert.assertSame(
+ "setArguments method uses different instance"
+ + " of empty Object array for getArgs",
+ getArgs, otherProperty.getGetArgs());
+ Assert.assertSame(
+ "setArguments method uses different instance"
+ + " of empty Object array for setArgs",
+ setArgs, otherProperty.getSetArgs());
+ }
+
+ @Test
+ public void testDefaultArgsSerialization()
+ throws IOException, ClassNotFoundException {
+ TestBean bean = new TestBean();
+ TestMethodProperty<String> property = new TestMethodProperty<String>(
+ bean, "name");
+
+ ByteArrayOutputStream sourceOutStream = new ByteArrayOutputStream();
+ ObjectOutputStream outStream = new ObjectOutputStream(sourceOutStream);
+ outStream.writeObject(property);
+
+ ObjectInputStream inputStream = new ObjectInputStream(
+ new ByteArrayInputStream(sourceOutStream.toByteArray()));
+ Object red = inputStream.readObject();
+ TestMethodProperty<?> deserialized = (TestMethodProperty<?>) red;
+
+ Assert.assertNotNull("Deseriliation doesn't call setArguments method",
+ deserialized.getGetArgs());
+ Assert.assertNotNull("Deseriliation doesn't call setArguments method",
+ deserialized.getSetArgs());
+
+ }
+
+ public static class TestMethodProperty<T> extends MethodProperty<T> {
+
+ public TestMethodProperty(Object instance, String beanPropertyName) {
+ super(instance, beanPropertyName);
+ }
+
+ @Override
+ public void setArguments(Object[] getArgs, Object[] setArgs,
+ int setArgumentIndex) {
+ super.setArguments(getArgs, setArgs, setArgumentIndex);
+ this.getArgs = getArgs;
+ this.setArgs = setArgs;
+ }
+
+ Object[] getGetArgs() {
+ return getArgs;
+ }
+
+ Object[] getSetArgs() {
+ return setArgs;
+ }
+
+ private transient Object[] getArgs;
+ private transient Object[] setArgs;
+ }
+
+ public static class TestBean implements Serializable {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java
new file mode 100644
index 0000000000..4a1e2a1784
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java
@@ -0,0 +1,351 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class NestedMethodPropertyTest {
+
+ public static class Address implements Serializable {
+ private String street;
+ private int postalCodePrimitive;
+ private Integer postalCodeObject;
+
+ public Address(String street, int postalCode) {
+ this.street = street;
+ postalCodePrimitive = postalCode;
+ postalCodeObject = postalCode;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setPostalCodePrimitive(int postalCodePrimitive) {
+ this.postalCodePrimitive = postalCodePrimitive;
+ }
+
+ public int getPostalCodePrimitive() {
+ return postalCodePrimitive;
+ }
+
+ public void setPostalCodeObject(Integer postalCodeObject) {
+ this.postalCodeObject = postalCodeObject;
+ }
+
+ public Integer getPostalCodeObject() {
+ return postalCodeObject;
+ }
+
+ // read-only boolean property
+ public boolean isBoolean() {
+ return true;
+ }
+ }
+
+ public static class Person implements Serializable {
+ private String name;
+ private Address address;
+ private int age;
+
+ public Person(String name, Address address) {
+ this.name = name;
+ this.address = address;
+ }
+
+ public Person(String name, Address address, int age) {
+ this.name = name;
+ this.address = address;
+ this.age = age;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+ }
+
+ public static class Team implements Serializable {
+ private String name;
+ private Person manager;
+
+ public Team(String name, Person manager) {
+ this.name = name;
+ this.manager = manager;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setManager(Person manager) {
+ this.manager = manager;
+ }
+
+ public Person getManager() {
+ return manager;
+ }
+ }
+
+ private Address oldMill;
+ private Person joonas;
+ private Team vaadin;
+
+ @Before
+ public void setUp() {
+ oldMill = new Address("Ruukinkatu 2-4", 20540);
+ joonas = new Person("Joonas", oldMill);
+ vaadin = new Team("Vaadin", joonas);
+ }
+
+ @Test
+ public void testSingleLevelNestedSimpleProperty() {
+ NestedMethodProperty<String> nameProperty = new NestedMethodProperty<String>(
+ vaadin, "name");
+
+ Assert.assertEquals(String.class, nameProperty.getType());
+ Assert.assertEquals("Vaadin", nameProperty.getValue());
+ }
+
+ @Test
+ public void testSingleLevelNestedObjectProperty() {
+ NestedMethodProperty<Person> managerProperty = new NestedMethodProperty<Person>(
+ vaadin, "manager");
+
+ Assert.assertEquals(Person.class, managerProperty.getType());
+ Assert.assertEquals(joonas, managerProperty.getValue());
+ }
+
+ @Test
+ public void testMultiLevelNestedProperty() {
+ NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.name");
+ NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>(
+ vaadin, "manager.address");
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+ NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>(
+ vaadin, "manager.address.postalCodePrimitive");
+ NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>(
+ vaadin, "manager.address.postalCodeObject");
+ NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>(
+ vaadin, "manager.address.boolean");
+
+ Assert.assertEquals(String.class, managerNameProperty.getType());
+ Assert.assertEquals("Joonas", managerNameProperty.getValue());
+
+ Assert.assertEquals(Address.class, addressProperty.getType());
+ Assert.assertEquals(oldMill, addressProperty.getValue());
+
+ Assert.assertEquals(String.class, streetProperty.getType());
+ Assert.assertEquals("Ruukinkatu 2-4", streetProperty.getValue());
+
+ Assert.assertEquals(Integer.class,
+ postalCodePrimitiveProperty.getType());
+ Assert.assertEquals(Integer.valueOf(20540),
+ postalCodePrimitiveProperty.getValue());
+
+ Assert.assertEquals(Integer.class, postalCodeObjectProperty.getType());
+ Assert.assertEquals(Integer.valueOf(20540),
+ postalCodeObjectProperty.getValue());
+
+ Assert.assertEquals(Boolean.class, booleanProperty.getType());
+ Assert.assertEquals(Boolean.TRUE, booleanProperty.getValue());
+ }
+
+ @Test
+ public void testEmptyPropertyName() {
+ try {
+ new NestedMethodProperty<Object>(vaadin, "");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+
+ try {
+ new NestedMethodProperty<Object>(vaadin, " ");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ }
+
+ @Test
+ public void testInvalidPropertyName() {
+ try {
+ new NestedMethodProperty<Object>(vaadin, ".");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ try {
+ new NestedMethodProperty<Object>(vaadin, ".manager");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ try {
+ new NestedMethodProperty<Object>(vaadin, "manager.");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ try {
+ new NestedMethodProperty<Object>(vaadin, "manager..name");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ }
+
+ @Test
+ public void testInvalidNestedPropertyName() {
+ try {
+ new NestedMethodProperty<Object>(vaadin, "member");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+
+ try {
+ new NestedMethodProperty<Object>(vaadin, "manager.pet");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+
+ try {
+ new NestedMethodProperty<Object>(vaadin, "manager.address.city");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // should get exception
+ }
+ }
+
+ @Test
+ public void testNullNestedProperty() {
+ NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.name");
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+
+ joonas.setAddress(null);
+ assertNull(streetProperty.getValue());
+
+ vaadin.setManager(null);
+ assertNull(managerNameProperty.getValue());
+ assertNull(streetProperty.getValue());
+
+ vaadin.setManager(joonas);
+ Assert.assertEquals("Joonas", managerNameProperty.getValue());
+ Assert.assertNull(streetProperty.getValue());
+
+ }
+
+ @Test
+ public void testMultiLevelNestedPropertySetValue() {
+ NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.name");
+ NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>(
+ vaadin, "manager.address");
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+ NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>(
+ vaadin, "manager.address.postalCodePrimitive");
+ NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>(
+ vaadin, "manager.address.postalCodeObject");
+
+ managerNameProperty.setValue("Joonas L");
+ Assert.assertEquals("Joonas L", joonas.getName());
+ streetProperty.setValue("Ruukinkatu");
+ Assert.assertEquals("Ruukinkatu", oldMill.getStreet());
+ postalCodePrimitiveProperty.setValue(0);
+ postalCodeObjectProperty.setValue(1);
+ Assert.assertEquals(0, oldMill.getPostalCodePrimitive());
+ Assert.assertEquals(Integer.valueOf(1), oldMill.getPostalCodeObject());
+
+ postalCodeObjectProperty.setValue(null);
+ Assert.assertNull(oldMill.getPostalCodeObject());
+
+ Address address2 = new Address("Other street", 12345);
+ addressProperty.setValue(address2);
+ Assert.assertEquals("Other street", streetProperty.getValue());
+ }
+
+ @Test
+ public void testSerialization() throws IOException, ClassNotFoundException {
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new ObjectOutputStream(baos).writeObject(streetProperty);
+ @SuppressWarnings("unchecked")
+ NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray())).readObject();
+
+ Assert.assertEquals("Ruukinkatu 2-4", property2.getValue());
+ }
+
+ @Test
+ public void testSerializationWithIntermediateNull()
+ throws IOException, ClassNotFoundException {
+ vaadin.setManager(null);
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new ObjectOutputStream(baos).writeObject(streetProperty);
+ @SuppressWarnings("unchecked")
+ NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray())).readObject();
+
+ Assert.assertNull(property2.getValue());
+ }
+
+ @Test
+ public void testIsReadOnly() {
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+ NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>(
+ vaadin, "manager.address.boolean");
+
+ Assert.assertFalse(streetProperty.isReadOnly());
+ Assert.assertTrue(booleanProperty.isReadOnly());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java
new file mode 100644
index 0000000000..e0307034cf
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java
@@ -0,0 +1,102 @@
+package com.vaadin.data.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ObjectPropertyTest {
+
+ public static class TestSuperClass {
+ private String name;
+
+ public TestSuperClass(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+ }
+
+ public static class TestSubClass extends TestSuperClass {
+ public TestSubClass(String name) {
+ super("Subclass: " + name);
+ }
+ }
+
+ private TestSuperClass super1 = new TestSuperClass("super1");
+ private TestSubClass sub1 = new TestSubClass("sub1");
+
+ @Test
+ public void testSimple() {
+ ObjectProperty<TestSuperClass> prop1 = new ObjectProperty<TestSuperClass>(
+ super1, TestSuperClass.class);
+ Assert.assertEquals("super1", prop1.getValue().getName());
+ prop1 = new ObjectProperty<TestSuperClass>(super1);
+ Assert.assertEquals("super1", prop1.getValue().getName());
+
+ ObjectProperty<TestSubClass> prop2 = new ObjectProperty<TestSubClass>(
+ sub1, TestSubClass.class);
+ Assert.assertEquals("Subclass: sub1", prop2.getValue().getName());
+ prop2 = new ObjectProperty<TestSubClass>(sub1);
+ Assert.assertEquals("Subclass: sub1", prop2.getValue().getName());
+ }
+
+ @Test
+ public void testSetValueObjectSuper() {
+ ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>(
+ super1, TestSuperClass.class);
+ Assert.assertEquals("super1", prop.getValue().getName());
+ prop.setValue(new TestSuperClass("super2"));
+ Assert.assertEquals("super1", super1.getName());
+ Assert.assertEquals("super2", prop.getValue().getName());
+ }
+
+ @Test
+ public void testSetValueObjectSub() {
+ ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>(
+ sub1, TestSubClass.class);
+ Assert.assertEquals("Subclass: sub1", prop.getValue().getName());
+ prop.setValue(new TestSubClass("sub2"));
+ Assert.assertEquals("Subclass: sub1", sub1.getName());
+ Assert.assertEquals("Subclass: sub2", prop.getValue().getName());
+ }
+
+ @Test
+ public void testSetValueStringSuper() {
+ ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>(
+ super1, TestSuperClass.class);
+ Assert.assertEquals("super1", prop.getValue().getName());
+ prop.setValue(new TestSuperClass("super2"));
+ Assert.assertEquals("super1", super1.getName());
+ Assert.assertEquals("super2", prop.getValue().getName());
+ }
+
+ @Test
+ public void testSetValueStringSub() {
+ ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>(
+ sub1, TestSubClass.class);
+ Assert.assertEquals("Subclass: sub1", prop.getValue().getName());
+ prop.setValue(new TestSubClass("sub2"));
+ Assert.assertEquals("Subclass: sub1", sub1.getName());
+ Assert.assertEquals("Subclass: sub2", prop.getValue().getName());
+ }
+
+ @Test
+ public void testMixedGenerics() {
+ ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>(
+ sub1);
+ Assert.assertEquals("Subclass: sub1", prop.getValue().getName());
+ Assert.assertEquals(prop.getType(), TestSubClass.class);
+ // create correct subclass based on the runtime type of the instance
+ // given to ObjectProperty constructor, which is a subclass of the type
+ // parameter
+ prop.setValue(new TestSubClass("sub2"));
+ Assert.assertEquals("Subclass: sub2", prop.getValue().getName());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java
new file mode 100644
index 0000000000..5f64c0e8d8
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java
@@ -0,0 +1,120 @@
+package com.vaadin.data.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PerformanceTestIndexedContainerTest {
+
+ private static final int REPEATS = 10;
+ private final static int ITEMS = 50000;
+ private static final long ADD_ITEM_FAIL_THRESHOLD = 200;
+ // TODO should improve performance of these methods
+ private static final long ADD_ITEM_AT_FAIL_THRESHOLD = 5000;
+ private static final long ADD_ITEM_AFTER_FAIL_THRESHOLD = 5000;
+ private static final long ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD = 5000;
+ private static final long ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD = 200;
+
+ @Test
+ public void testAddItemPerformance() {
+ Collection<Long> times = new ArrayList<Long>();
+ for (int j = 0; j < REPEATS; ++j) {
+ IndexedContainer c = new IndexedContainer();
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < ITEMS; i++) {
+ c.addItem();
+ }
+ times.add(System.currentTimeMillis() - start);
+ }
+ checkMedian(ITEMS, times, "IndexedContainer.addItem()",
+ ADD_ITEM_FAIL_THRESHOLD);
+ }
+
+ @Test
+ public void testAddItemAtPerformance() {
+ Collection<Long> times = new ArrayList<Long>();
+ for (int j = 0; j < REPEATS; ++j) {
+ IndexedContainer c = new IndexedContainer();
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < ITEMS; i++) {
+ c.addItemAt(0);
+ }
+ times.add(System.currentTimeMillis() - start);
+ }
+ checkMedian(ITEMS, times, "IndexedContainer.addItemAt()",
+ ADD_ITEM_AT_FAIL_THRESHOLD);
+ }
+
+ @Test
+ public void testAddItemAfterPerformance() {
+ Object initialId = "Item0";
+ Collection<Long> times = new ArrayList<Long>();
+ for (int j = 0; j < REPEATS; ++j) {
+ IndexedContainer c = new IndexedContainer();
+ c.addItem(initialId);
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < ITEMS; i++) {
+ c.addItemAfter(initialId);
+ }
+ times.add(System.currentTimeMillis() - start);
+ }
+ checkMedian(ITEMS, times, "IndexedContainer.addItemAfter()",
+ ADD_ITEM_AFTER_FAIL_THRESHOLD);
+ }
+
+ @Test
+ public void testAddItemAfterLastPerformance() {
+ // TODO running with less items because slow otherwise
+ Collection<Long> times = new ArrayList<Long>();
+ for (int j = 0; j < REPEATS; ++j) {
+ IndexedContainer c = new IndexedContainer();
+ c.addItem();
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < ITEMS / 3; i++) {
+ c.addItemAfter(c.lastItemId());
+ }
+ times.add(System.currentTimeMillis() - start);
+ }
+ checkMedian(ITEMS / 3, times, "IndexedContainer.addItemAfter(lastId)",
+ ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD);
+ }
+
+ @Test
+ public void testAddItemsConstructorPerformance() {
+ Collection<Object> items = new ArrayList<Object>(50000);
+ for (int i = 0; i < ITEMS; ++i) {
+ items.add(new Object());
+ }
+
+ SortedSet<Long> times = new TreeSet<Long>();
+ for (int j = 0; j < REPEATS; ++j) {
+ long start = System.currentTimeMillis();
+ new IndexedContainer(items);
+ times.add(System.currentTimeMillis() - start);
+ }
+ checkMedian(ITEMS, times, "IndexedContainer(Collection)",
+ ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD);
+ }
+
+ private void checkMedian(int items, Collection<Long> times,
+ String methodName, long threshold) {
+ long median = median(times);
+ System.out.println(
+ methodName + " timings (ms) for " + items + " items: " + times);
+ Assert.assertTrue(methodName + " too slow, median time " + median
+ + "ms for " + items + " items", median <= threshold);
+ }
+
+ private Long median(Collection<Long> times) {
+ ArrayList<Long> list = new ArrayList<Long>(times);
+ Collections.sort(list);
+ // not exact median in some cases, but good enough
+ return list.get(list.size() / 2);
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java
new file mode 100644
index 0000000000..af9db229c5
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java
@@ -0,0 +1,84 @@
+package com.vaadin.data.util;
+
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Property;
+import com.vaadin.data.util.NestedMethodPropertyTest.Person;
+
+public class PropertyDescriptorTest {
+
+ @Test
+ public void testMethodPropertyDescriptorSerialization() throws Exception {
+ PropertyDescriptor[] pds = Introspector.getBeanInfo(Person.class)
+ .getPropertyDescriptors();
+
+ MethodPropertyDescriptor<Person> descriptor = null;
+
+ for (PropertyDescriptor pd : pds) {
+ if ("name".equals(pd.getName())) {
+ descriptor = new MethodPropertyDescriptor<Person>(pd.getName(),
+ String.class, pd.getReadMethod(), pd.getWriteMethod());
+ break;
+ }
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new ObjectOutputStream(baos).writeObject(descriptor);
+ @SuppressWarnings("unchecked")
+ VaadinPropertyDescriptor<Person> descriptor2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray())).readObject();
+
+ Property<?> property = descriptor2
+ .createProperty(new Person("John", null));
+ Assert.assertEquals("John", property.getValue());
+ }
+
+ @Test
+ public void testSimpleNestedPropertyDescriptorSerialization()
+ throws Exception {
+ NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>(
+ "name", Person.class);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new ObjectOutputStream(baos).writeObject(pd);
+ @SuppressWarnings("unchecked")
+ VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray())).readObject();
+
+ Property<?> property = pd2.createProperty(new Person("John", null));
+ Assert.assertEquals("John", property.getValue());
+ }
+
+ @Test
+ public void testNestedPropertyDescriptorSerialization() throws Exception {
+ NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>(
+ "address.street", Person.class);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new ObjectOutputStream(baos).writeObject(pd);
+ @SuppressWarnings("unchecked")
+ VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray())).readObject();
+
+ Property<?> property = pd2.createProperty(new Person("John", null));
+ Assert.assertNull(property.getValue());
+ }
+
+ @Test
+ public void testMethodPropertyDescriptorWithPrimitivePropertyType()
+ throws Exception {
+ MethodPropertyDescriptor<Person> pd = new MethodPropertyDescriptor<Person>(
+ "age", int.class, Person.class.getMethod("getAge"),
+ Person.class.getMethod("setAge", int.class));
+
+ Assert.assertEquals(Integer.class, pd.getPropertyType());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java
new file mode 100644
index 0000000000..fc91a20dd0
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java
@@ -0,0 +1,432 @@
+package com.vaadin.data.util;
+
+import java.util.Iterator;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Item.PropertySetChangeEvent;
+import com.vaadin.data.Item.PropertySetChangeListener;
+
+public class PropertySetItemTest {
+
+ private static final String ID1 = "id1";
+ private static final String ID2 = "id2";
+ private static final String ID3 = "id3";
+
+ private static final String VALUE1 = "value1";
+ private static final String VALUE2 = "value2";
+ private static final String VALUE3 = "value3";
+
+ private ObjectProperty<String> prop1;
+ private ObjectProperty<String> prop2;
+ private ObjectProperty<String> prop3;
+
+ private PropertySetChangeListener propertySetListenerMock;
+ private PropertySetChangeListener propertySetListenerMock2;
+
+ @Before
+ public void setUp() {
+ prop1 = new ObjectProperty<String>(VALUE1, String.class);
+ prop2 = new ObjectProperty<String>(VALUE2, String.class);
+ prop3 = new ObjectProperty<String>(VALUE3, String.class);
+
+ propertySetListenerMock = EasyMock
+ .createStrictMock(PropertySetChangeListener.class);
+ propertySetListenerMock2 = EasyMock
+ .createMock(PropertySetChangeListener.class);
+ }
+
+ @After
+ public void tearDown() {
+ prop1 = null;
+ prop2 = null;
+ prop3 = null;
+
+ propertySetListenerMock = null;
+ propertySetListenerMock2 = null;
+ }
+
+ private PropertysetItem createPropertySetItem() {
+ return new PropertysetItem();
+ }
+
+ @Test
+ public void testEmptyItem() {
+ PropertysetItem item = createPropertySetItem();
+ Assert.assertNotNull(item.getItemPropertyIds());
+ Assert.assertEquals(0, item.getItemPropertyIds().size());
+ }
+
+ @Test
+ public void testGetProperty() {
+ PropertysetItem item = createPropertySetItem();
+
+ Assert.assertNull(item.getItemProperty(ID1));
+
+ item.addItemProperty(ID1, prop1);
+
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+ Assert.assertNull(item.getItemProperty(ID2));
+ }
+
+ @Test
+ public void testAddSingleProperty() {
+ PropertysetItem item = createPropertySetItem();
+
+ item.addItemProperty(ID1, prop1);
+ Assert.assertEquals(1, item.getItemPropertyIds().size());
+ Object firstValue = item.getItemPropertyIds().iterator().next();
+ Assert.assertEquals(ID1, firstValue);
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+ }
+
+ @Test
+ public void testAddMultipleProperties() {
+ PropertysetItem item = createPropertySetItem();
+
+ item.addItemProperty(ID1, prop1);
+ Assert.assertEquals(1, item.getItemPropertyIds().size());
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+
+ item.addItemProperty(ID2, prop2);
+ Assert.assertEquals(2, item.getItemPropertyIds().size());
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+ Assert.assertEquals(prop2, item.getItemProperty(ID2));
+
+ item.addItemProperty(ID3, prop3);
+ Assert.assertEquals(3, item.getItemPropertyIds().size());
+ }
+
+ @Test
+ public void testAddedPropertyOrder() {
+ PropertysetItem item = createPropertySetItem();
+ item.addItemProperty(ID1, prop1);
+ item.addItemProperty(ID2, prop2);
+ item.addItemProperty(ID3, prop3);
+
+ Iterator<?> it = item.getItemPropertyIds().iterator();
+ Assert.assertEquals(ID1, it.next());
+ Assert.assertEquals(ID2, it.next());
+ Assert.assertEquals(ID3, it.next());
+ }
+
+ @Test
+ public void testAddPropertyTwice() {
+ PropertysetItem item = createPropertySetItem();
+ Assert.assertTrue(item.addItemProperty(ID1, prop1));
+ Assert.assertFalse(item.addItemProperty(ID1, prop1));
+
+ Assert.assertEquals(1, item.getItemPropertyIds().size());
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+ }
+
+ @Test
+ public void testCannotChangeProperty() {
+ PropertysetItem item = createPropertySetItem();
+ Assert.assertTrue(item.addItemProperty(ID1, prop1));
+
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+
+ Assert.assertFalse(item.addItemProperty(ID1, prop2));
+
+ Assert.assertEquals(1, item.getItemPropertyIds().size());
+ Assert.assertEquals(prop1, item.getItemProperty(ID1));
+ }
+
+ @Test
+ public void testRemoveProperty() {
+ PropertysetItem item = createPropertySetItem();
+ item.addItemProperty(ID1, prop1);
+ item.removeItemProperty(ID1);
+
+ Assert.assertEquals(0, item.getItemPropertyIds().size());
+ Assert.assertNull(item.getItemProperty(ID1));
+ }
+
+ @Test
+ public void testRemovePropertyOrder() {
+ PropertysetItem item = createPropertySetItem();
+ item.addItemProperty(ID1, prop1);
+ item.addItemProperty(ID2, prop2);
+ item.addItemProperty(ID3, prop3);
+
+ item.removeItemProperty(ID2);
+
+ Iterator<?> it = item.getItemPropertyIds().iterator();
+ Assert.assertEquals(ID1, it.next());
+ Assert.assertEquals(ID3, it.next());
+ }
+
+ @Test
+ public void testRemoveNonExistentListener() {
+ PropertysetItem item = createPropertySetItem();
+ item.removeListener(propertySetListenerMock);
+ }
+
+ @Test
+ public void testRemoveListenerTwice() {
+ PropertysetItem item = createPropertySetItem();
+ item.addListener(propertySetListenerMock);
+ item.removeListener(propertySetListenerMock);
+ item.removeListener(propertySetListenerMock);
+ }
+
+ @Test
+ public void testAddPropertyNotification() {
+ // exactly one notification each time
+ PropertysetItem item = createPropertySetItem();
+
+ // Expectations and start test
+ propertySetListenerMock.itemPropertySetChange(
+ EasyMock.isA(PropertySetChangeEvent.class));
+ EasyMock.replay(propertySetListenerMock);
+
+ // Add listener and add a property -> should end up in listener once
+ item.addListener(propertySetListenerMock);
+ item.addItemProperty(ID1, prop1);
+
+ // Ensure listener was called once
+ EasyMock.verify(propertySetListenerMock);
+
+ // Remove the listener -> should not end up in listener when adding a
+ // property
+ item.removeListener(propertySetListenerMock);
+ item.addItemProperty(ID2, prop2);
+
+ // Ensure listener still has been called only once
+ EasyMock.verify(propertySetListenerMock);
+ }
+
+ @Test
+ public void testRemovePropertyNotification() {
+ // exactly one notification each time
+ PropertysetItem item = createPropertySetItem();
+ item.addItemProperty(ID1, prop1);
+ item.addItemProperty(ID2, prop2);
+
+ // Expectations and start test
+ propertySetListenerMock.itemPropertySetChange(
+ EasyMock.isA(PropertySetChangeEvent.class));
+ EasyMock.replay(propertySetListenerMock);
+
+ // Add listener and add a property -> should end up in listener once
+ item.addListener(propertySetListenerMock);
+ item.removeItemProperty(ID1);
+
+ // Ensure listener was called once
+ EasyMock.verify(propertySetListenerMock);
+
+ // Remove the listener -> should not end up in listener
+ item.removeListener(propertySetListenerMock);
+ item.removeItemProperty(ID2);
+
+ // Ensure listener still has been called only once
+ EasyMock.verify(propertySetListenerMock);
+ }
+
+ @Test
+ public void testItemEqualsNull() {
+ PropertysetItem item = createPropertySetItem();
+
+ Assert.assertFalse(item.equals(null));
+ }
+
+ @Test
+ public void testEmptyItemEquals() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ Assert.assertTrue(item1.equals(item2));
+ }
+
+ @Test
+ public void testItemEqualsSingleProperty() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+ item2.addItemProperty(ID1, prop1);
+ PropertysetItem item3 = createPropertySetItem();
+ item3.addItemProperty(ID1, prop1);
+ PropertysetItem item4 = createPropertySetItem();
+ item4.addItemProperty(ID1, prop2);
+ PropertysetItem item5 = createPropertySetItem();
+ item5.addItemProperty(ID2, prop2);
+
+ Assert.assertFalse(item1.equals(item2));
+ Assert.assertFalse(item1.equals(item3));
+ Assert.assertFalse(item1.equals(item4));
+ Assert.assertFalse(item1.equals(item5));
+
+ Assert.assertTrue(item2.equals(item3));
+ Assert.assertFalse(item2.equals(item4));
+ Assert.assertFalse(item2.equals(item5));
+
+ Assert.assertFalse(item3.equals(item4));
+ Assert.assertFalse(item3.equals(item5));
+
+ Assert.assertFalse(item4.equals(item5));
+
+ Assert.assertFalse(item2.equals(item1));
+ }
+
+ @Test
+ public void testItemEqualsMultipleProperties() {
+ PropertysetItem item1 = createPropertySetItem();
+ item1.addItemProperty(ID1, prop1);
+
+ PropertysetItem item2 = createPropertySetItem();
+ item2.addItemProperty(ID1, prop1);
+ item2.addItemProperty(ID2, prop2);
+
+ PropertysetItem item3 = createPropertySetItem();
+ item3.addItemProperty(ID1, prop1);
+ item3.addItemProperty(ID2, prop2);
+
+ Assert.assertFalse(item1.equals(item2));
+
+ Assert.assertTrue(item2.equals(item3));
+ }
+
+ @Test
+ public void testItemEqualsPropertyOrder() {
+ PropertysetItem item1 = createPropertySetItem();
+ item1.addItemProperty(ID1, prop1);
+ item1.addItemProperty(ID2, prop2);
+
+ PropertysetItem item2 = createPropertySetItem();
+ item2.addItemProperty(ID2, prop2);
+ item2.addItemProperty(ID1, prop1);
+
+ Assert.assertFalse(item1.equals(item2));
+ }
+
+ @Test
+ public void testEqualsSingleListener() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ item1.addListener(propertySetListenerMock);
+
+ Assert.assertFalse(item1.equals(item2));
+ Assert.assertFalse(item2.equals(item1));
+
+ item2.addListener(propertySetListenerMock);
+
+ Assert.assertTrue(item1.equals(item2));
+ Assert.assertTrue(item2.equals(item1));
+ }
+
+ @Test
+ public void testEqualsMultipleListeners() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ item1.addListener(propertySetListenerMock);
+ item1.addListener(propertySetListenerMock2);
+
+ item2.addListener(propertySetListenerMock);
+
+ Assert.assertFalse(item1.equals(item2));
+ Assert.assertFalse(item2.equals(item1));
+
+ item2.addListener(propertySetListenerMock2);
+
+ Assert.assertTrue(item1.equals(item2));
+ Assert.assertTrue(item2.equals(item1));
+ }
+
+ @Test
+ public void testEqualsAddRemoveListener() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ item1.addListener(propertySetListenerMock);
+ item1.removeListener(propertySetListenerMock);
+
+ Assert.assertTrue(item1.equals(item2));
+ Assert.assertTrue(item2.equals(item1));
+ }
+
+ @Test
+ public void testItemHashCodeEmpty() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+ }
+
+ @Test
+ public void testItemHashCodeAddProperties() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+
+ item1.addItemProperty(ID1, prop1);
+ item1.addItemProperty(ID2, prop2);
+ // hashCodes can be equal even if items are different
+
+ item2.addItemProperty(ID1, prop1);
+ item2.addItemProperty(ID2, prop2);
+ // but here hashCodes must be equal
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+ }
+
+ @Test
+ public void testItemHashCodeAddListeners() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+
+ item1.addListener(propertySetListenerMock);
+ // hashCodes can be equal even if items are different
+
+ item2.addListener(propertySetListenerMock);
+ // but here hashCodes must be equal
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+ }
+
+ @Test
+ public void testItemHashCodeAddRemoveProperty() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ item1.addItemProperty(ID1, prop1);
+ item1.removeItemProperty(ID1);
+
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+ }
+
+ @Test
+ public void testItemHashCodeAddRemoveListener() {
+ PropertysetItem item1 = createPropertySetItem();
+ PropertysetItem item2 = createPropertySetItem();
+
+ item1.addListener(propertySetListenerMock);
+ item1.removeListener(propertySetListenerMock);
+
+ Assert.assertEquals(item1.hashCode(), item2.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ // toString() behavior is specified in the class javadoc
+ PropertysetItem item = createPropertySetItem();
+
+ Assert.assertEquals("", item.toString());
+
+ item.addItemProperty(ID1, prop1);
+
+ Assert.assertEquals(String.valueOf(prop1.getValue()), item.toString());
+
+ item.addItemProperty(ID2, prop2);
+
+ Assert.assertEquals(String.valueOf(prop1.getValue()) + " "
+ + String.valueOf(prop2.getValue()), item.toString());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java
new file mode 100644
index 0000000000..df4258f316
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java
@@ -0,0 +1,35 @@
+package com.vaadin.data.util;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.fieldgroup.PropertyId;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class ReflectToolsGetSuperFieldTest {
+
+ @Test
+ public void getFieldFromSuperClass() {
+ class MyClass {
+ @PropertyId("testProperty")
+ LegacyTextField test = new LegacyTextField("This is a test");
+ }
+ class MySubClass extends MyClass {
+ // no fields here
+ }
+
+ PropertysetItem item = new PropertysetItem();
+ item.addItemProperty("testProperty",
+ new ObjectProperty<String>("Value of testProperty"));
+
+ MySubClass form = new MySubClass();
+
+ FieldGroup binder = new FieldGroup(item);
+ binder.bindMemberFields(form);
+
+ assertTrue("Value of testProperty".equals(form.test.getValue()));
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java
new file mode 100644
index 0000000000..ef3e416f96
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2016 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.util;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.v7.ui.LegacyTextField;
+
+/**
+ * Test verifying that TransactionalPropertyWrapper removes it's listener from
+ * wrapped Property
+ *
+ * @since 7.1.15
+ * @author Vaadin Ltd
+ */
+public class TransactionalPropertyWrapperTest {
+
+ @SuppressWarnings("serial")
+ public class TestingProperty<T extends Object>
+ extends ObjectProperty<Object> {
+
+ private List<ValueChangeListener> listeners = new ArrayList<ValueChangeListener>();
+
+ public TestingProperty(Object value) {
+ super(value);
+ }
+
+ @Override
+ public void addValueChangeListener(ValueChangeListener listener) {
+ super.addValueChangeListener(listener);
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeValueChangeListener(ValueChangeListener listener) {
+ super.removeValueChangeListener(listener);
+ if (listeners.contains(listener)) {
+ listeners.remove(listener);
+ }
+ }
+
+ public boolean hasListeners() {
+ return !listeners.isEmpty();
+ }
+ }
+
+ private final LegacyTextField nameField = new LegacyTextField("Name");
+ private final LegacyTextField ageField = new LegacyTextField("Age");
+ private final LegacyTextField unboundField = new LegacyTextField(
+ "No FieldGroup");
+ private final TestingProperty<String> unboundProp = new TestingProperty<String>(
+ "Hello World");
+ private final PropertysetItem item = new PropertysetItem();
+
+ @Test
+ public void fieldGroupBindAndUnbind() {
+ item.addItemProperty("name",
+ new TestingProperty<String>("Just some text"));
+ item.addItemProperty("age", new TestingProperty<String>("42"));
+
+ final FieldGroup binder = new FieldGroup(item);
+ binder.setBuffered(false);
+
+ for (int i = 0; i < 2; ++i) {
+ binder.bind(nameField, "name");
+ binder.bind(ageField, "age");
+ unboundField.setPropertyDataSource(unboundProp);
+
+ assertTrue("No listeners in Properties", fieldsHaveListeners(true));
+
+ binder.unbind(nameField);
+ binder.unbind(ageField);
+ unboundField.setPropertyDataSource(null);
+
+ assertTrue("Listeners in Properties after unbinding",
+ fieldsHaveListeners(false));
+ }
+ }
+
+ /**
+ * Check that all listeners have same hasListeners() response
+ *
+ * @param expected
+ * expected response
+ * @return true if all are the same as expected. false if not
+ */
+ private boolean fieldsHaveListeners(boolean expected) {
+ for (Object id : item.getItemPropertyIds()) {
+ TestingProperty<?> itemProperty = (TestingProperty<?>) item
+ .getItemProperty(id);
+
+ if (itemProperty.hasListeners() != expected) {
+ return false;
+ }
+ }
+ return unboundProp.hasListeners() == expected;
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java
new file mode 100644
index 0000000000..1b93a3063d
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2000-2016 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;
+
+import java.util.EventObject;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.event.ContextClickEvent;
+import com.vaadin.event.ContextClickEvent.ContextClickListener;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.LegacyGrid.GridContextClickEvent;
+import com.vaadin.ui.Table.TableContextClickEvent;
+
+/**
+ * Server-side unit tests to see that context click events are sent to listeners
+ * correctly.
+ *
+ * If a listener is listening to a super type of an event, it should get the
+ * event. i.e. Listening to ContextClickEvent, it should get the specialized
+ * GridContextClickEvent as well.
+ *
+ * If a listener is listening to a sub-type of an event, it should not get the
+ * super version. i.e. Listening to GridContextClickEvent, it should not get a
+ * plain ContextClickEvent.
+ */
+public class ContextClickListenerTest extends AbstractComponent {
+
+ private final static ContextClickEvent contextClickEvent = EasyMock
+ .createMock(ContextClickEvent.class);
+ private final static GridContextClickEvent gridContextClickEvent = EasyMock
+ .createMock(GridContextClickEvent.class);
+ private final static TableContextClickEvent tableContextClickEvent = EasyMock
+ .createMock(TableContextClickEvent.class);
+
+ private final AssertListener contextListener = new AssertListener();
+ private final AssertListener ctxtListener2 = new AssertListener();
+
+ public static class AssertListener implements ContextClickListener {
+
+ private Class<?> expected = null;
+ private String error = null;
+
+ @Override
+ public void contextClick(ContextClickEvent event) {
+ if (expected == null) {
+ error = "Unexpected context click event.";
+ return;
+ }
+
+ if (!expected.isAssignableFrom(event.getClass())) {
+ error = "Expected event type did not match the actual event.";
+ }
+
+ expected = null;
+ }
+
+ public <T extends ContextClickEvent> void expect(Class<T> clazz) {
+ validate();
+ expected = clazz;
+ }
+
+ public void validate() {
+ if (expected != null) {
+ Assert.fail("Expected context click never happened.");
+ } else if (error != null) {
+ Assert.fail(error);
+ }
+ }
+ }
+
+ @Test
+ public void testListenerGetsASubClass() {
+ addContextClickListener(contextListener);
+ contextListener.expect(GridContextClickEvent.class);
+ fireEvent(gridContextClickEvent);
+ }
+
+ @Test
+ public void testListenerGetsExactClass() {
+ addContextClickListener(contextListener);
+ contextListener.expect(ContextClickEvent.class);
+ fireEvent(contextClickEvent);
+ }
+
+ /**
+ * Multiple listeners should get fitting events.
+ */
+ @Test
+ public void testMultipleListenerGetEvents() {
+ addContextClickListener(ctxtListener2);
+ addContextClickListener(contextListener);
+
+ ctxtListener2.expect(GridContextClickEvent.class);
+ contextListener.expect(GridContextClickEvent.class);
+
+ fireEvent(gridContextClickEvent);
+ }
+
+ @Test
+ public void testAddAndRemoveListener() {
+ addContextClickListener(contextListener);
+ contextListener.expect(ContextClickEvent.class);
+
+ fireEvent(contextClickEvent);
+
+ removeContextClickListener(contextListener);
+
+ fireEvent(contextClickEvent);
+ }
+
+ @Test
+ public void testAddAndRemoveMultipleListeners() {
+ addContextClickListener(ctxtListener2);
+ addContextClickListener(contextListener);
+
+ ctxtListener2.expect(GridContextClickEvent.class);
+ contextListener.expect(GridContextClickEvent.class);
+ fireEvent(gridContextClickEvent);
+
+ removeContextClickListener(ctxtListener2);
+
+ contextListener.expect(GridContextClickEvent.class);
+ fireEvent(gridContextClickEvent);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void testExpectedEventNotReceived() {
+ addContextClickListener(contextListener);
+ contextListener.expect(GridContextClickEvent.class);
+ fireEvent(contextClickEvent);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void testUnexpectedEventReceived() {
+ addContextClickListener(contextListener);
+ fireEvent(gridContextClickEvent);
+ }
+
+ @Override
+ protected void fireEvent(EventObject event) {
+ super.fireEvent(event);
+
+ // Validate listeners automatically.
+ ctxtListener2.validate();
+ contextListener.validate();
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java
new file mode 100644
index 0000000000..f5c315b440
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java
@@ -0,0 +1,172 @@
+package com.vaadin.tests.server.component.fieldgroup;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.fieldgroup.BeanFieldGroup;
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.data.fieldgroup.PropertyId;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.ui.RichTextArea;
+import com.vaadin.v7.ui.LegacyField;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class BeanFieldGroupTest {
+
+ private static final String DEFAULT_FOR_BASIC_FIELD = "default";
+
+ public static class MyBean {
+
+ private String basicField = DEFAULT_FOR_BASIC_FIELD;
+
+ private String anotherField;
+
+ private MyNestedBean nestedBean = new MyNestedBean();
+
+ public MyNestedBean getNestedBean() {
+ return nestedBean;
+ }
+
+ /**
+ * @return the basicField
+ */
+ public String getBasicField() {
+ return basicField;
+ }
+
+ /**
+ * @param basicField
+ * the basicField to set
+ */
+ public void setBasicField(String basicField) {
+ this.basicField = basicField;
+ }
+
+ /**
+ * @return the anotherField
+ */
+ public String getAnotherField() {
+ return anotherField;
+ }
+
+ /**
+ * @param anotherField
+ * the anotherField to set
+ */
+ public void setAnotherField(String anotherField) {
+ this.anotherField = anotherField;
+ }
+ }
+
+ public static class MyNestedBean {
+
+ private String hello = "Hello world";
+
+ public String getHello() {
+ return hello;
+ }
+ }
+
+ public static class ViewStub {
+
+ LegacyTextField basicField = new LegacyTextField();
+
+ @PropertyId("anotherField")
+ LegacyTextField boundWithAnnotation = new LegacyTextField();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testStaticBindingHelper() {
+ MyBean myBean = new MyBean();
+
+ ViewStub viewStub = new ViewStub();
+ BeanFieldGroup<MyBean> bindFields = BeanFieldGroup
+ .bindFieldsUnbuffered(myBean, viewStub);
+
+ LegacyField<String> field = (LegacyField<String>) bindFields
+ .getField("basicField");
+ Assert.assertEquals(DEFAULT_FOR_BASIC_FIELD, myBean.basicField);
+ field.setValue("Foo");
+ Assert.assertEquals("Foo", myBean.basicField);
+
+ field = (LegacyField<String>) bindFields.getField("anotherField");
+ field.setValue("Foo");
+ Assert.assertEquals("Foo", myBean.anotherField);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testStaticBufferedBindingHelper() throws CommitException {
+ MyBean myBean = new MyBean();
+
+ ViewStub viewStub = new ViewStub();
+ BeanFieldGroup<MyBean> bindFields = BeanFieldGroup
+ .bindFieldsBuffered(myBean, viewStub);
+
+ LegacyField<String> basicField = (LegacyField<String>) bindFields
+ .getField("basicField");
+ basicField.setValue("Foo");
+ Assert.assertEquals(DEFAULT_FOR_BASIC_FIELD, myBean.basicField);
+
+ LegacyField<String> anotherField = (LegacyField<String>) bindFields
+ .getField("anotherField");
+ anotherField.setValue("Foo");
+ Assert.assertNull(myBean.anotherField);
+
+ bindFields.commit();
+
+ Assert.assertEquals("Foo", myBean.basicField);
+ Assert.assertEquals("Foo", myBean.anotherField);
+
+ }
+
+ @Test
+ public void buildAndBindNestedProperty() {
+
+ MyBean bean = new MyBean();
+
+ BeanFieldGroup<MyBean> bfg = new BeanFieldGroup<MyBean>(MyBean.class);
+ bfg.setItemDataSource(bean);
+
+ com.vaadin.v7.ui.LegacyField<?> helloField = bfg
+ .buildAndBind("Hello string", "nestedBean.hello");
+ assertEquals(bean.nestedBean.hello, helloField.getValue().toString());
+ }
+
+ @Test
+ public void buildAndBindNestedRichTextAreaProperty() {
+
+ MyBean bean = new MyBean();
+
+ BeanFieldGroup<MyBean> bfg = new BeanFieldGroup<MyBean>(MyBean.class);
+ bfg.setItemDataSource(bean);
+
+ RichTextArea helloField = bfg.buildAndBind("Hello string",
+ "nestedBean.hello", RichTextArea.class);
+ assertEquals(bean.nestedBean.hello, helloField.getValue().toString());
+ }
+
+ @Test
+ public void setDataSource_nullBean_nullBeanIsSetInDataSource() {
+ BeanFieldGroup<MyBean> group = new BeanFieldGroup<MyBean>(MyBean.class);
+
+ group.setItemDataSource((MyBean) null);
+
+ BeanItem<MyBean> dataSource = group.getItemDataSource();
+ Assert.assertNull("Data source is null for null bean", dataSource);
+ }
+
+ @Test
+ public void setDataSource_nullItem_nullDataSourceIsSet() {
+ BeanFieldGroup<MyBean> group = new BeanFieldGroup<MyBean>(MyBean.class);
+
+ group.setItemDataSource((Item) null);
+ BeanItem<MyBean> dataSource = group.getItemDataSource();
+ Assert.assertNull("Group returns not null data source", dataSource);
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java
new file mode 100644
index 0000000000..a324c02cfc
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java
@@ -0,0 +1,85 @@
+package com.vaadin.tests.server.component.fieldgroup;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.data.util.PropertysetItem;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class CaseInsensitiveBindingTest {
+
+ @Test
+ public void caseInsensitivityAndUnderscoreRemoval() {
+ PropertysetItem item = new PropertysetItem();
+ item.addItemProperty("LastName", new ObjectProperty<String>("Sparrow"));
+
+ class MyForm extends FormLayout {
+ LegacyTextField lastName = new LegacyTextField("Last name");
+
+ public MyForm() {
+
+ // Should bind to the LastName property
+ addComponent(lastName);
+ }
+ }
+
+ MyForm form = new MyForm();
+
+ FieldGroup binder = new FieldGroup(item);
+ binder.bindMemberFields(form);
+
+ assertTrue("Sparrow".equals(form.lastName.getValue()));
+ }
+
+ @Test
+ public void UnderscoreRemoval() {
+ PropertysetItem item = new PropertysetItem();
+ item.addItemProperty("first_name", new ObjectProperty<String>("Jack"));
+
+ class MyForm extends FormLayout {
+ LegacyTextField firstName = new LegacyTextField("First name");
+
+ public MyForm() {
+ // Should bind to the first_name property
+ addComponent(firstName);
+ }
+ }
+
+ MyForm form = new MyForm();
+
+ FieldGroup binder = new FieldGroup(item);
+ binder.bindMemberFields(form);
+
+ assertTrue("Jack".equals(form.firstName.getValue()));
+ }
+
+ @Test
+ public void perfectMatchPriority() {
+ PropertysetItem item = new PropertysetItem();
+ item.addItemProperty("first_name",
+ new ObjectProperty<String>("Not this"));
+ item.addItemProperty("firstName", new ObjectProperty<String>("This"));
+
+ class MyForm extends FormLayout {
+ LegacyTextField firstName = new LegacyTextField("First name");
+
+ public MyForm() {
+ // should bind to the firstName property, not first_name
+ // property
+ addComponent(firstName);
+ }
+ }
+
+ MyForm form = new MyForm();
+
+ FieldGroup binder = new FieldGroup(item);
+ binder.bindMemberFields(form);
+
+ assertTrue("This".equals(form.firstName.getValue()));
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java
new file mode 100644
index 0000000000..43d2bf8a6a
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2000-2016 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.fieldgroup;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.data.util.AbstractProperty;
+import com.vaadin.v7.data.Validator.InvalidValueException;
+import com.vaadin.v7.ui.LegacyField;
+import com.vaadin.v7.ui.LegacyTextField;
+
+/**
+ *
+ * Tests for {@link FieldGroup}.
+ *
+ * @author Vaadin Ltd
+ */
+public class FieldGroupTest {
+
+ @Test
+ public void setReadOnly_readOnlyAndNoDataSource_fieldIsReadOnly() {
+ FieldGroup fieldGroup = new FieldGroup();
+
+ LegacyTextField field = new LegacyTextField();
+ fieldGroup.bind(field, "property");
+
+ fieldGroup.setReadOnly(true);
+
+ Assert.assertTrue("Field is not read only", field.isReadOnly());
+ }
+
+ @Test
+ public void setReadOnly_writableAndNoDataSource_fieldIsWritable() {
+ FieldGroup fieldGroup = new FieldGroup();
+
+ LegacyTextField field = new LegacyTextField();
+ fieldGroup.bind(field, "property");
+
+ fieldGroup.setReadOnly(false);
+
+ Assert.assertFalse("Field is not writable", field.isReadOnly());
+ }
+
+ @Test
+ public void commit_validationFailed_allValidationFailuresAvailable()
+ throws CommitException {
+ FieldGroup fieldGroup = new FieldGroup();
+
+ fieldGroup.setItemDataSource(new TestItem());
+
+ LegacyTextField field1 = new LegacyTextField();
+ field1.setRequired(true);
+ fieldGroup.bind(field1, "prop1");
+
+ LegacyTextField field2 = new LegacyTextField();
+ field2.setRequired(true);
+ fieldGroup.bind(field2, "prop2");
+
+ Set<LegacyTextField> set = new HashSet<>(Arrays.asList(field1, field2));
+
+ try {
+ fieldGroup.commit();
+ Assert.fail("No commit exception is thrown");
+ } catch (CommitException exception) {
+ Map<LegacyField<?>, ? extends InvalidValueException> invalidFields = exception
+ .getInvalidFields();
+ for (Entry<LegacyField<?>, ? extends InvalidValueException> entry : invalidFields
+ .entrySet()) {
+ set.remove(entry.getKey());
+ }
+ Assert.assertEquals(
+ "Some fields are not found in the invalid fields map", 0,
+ set.size());
+ Assert.assertEquals(
+ "Invalid value exception should be thrown for each field",
+ 2, invalidFields.size());
+ }
+ }
+
+ private static class TestItem implements Item {
+
+ @Override
+ public Property<String> getItemProperty(Object id) {
+ return new StringProperty();
+ }
+
+ @Override
+ public Collection<?> getItemPropertyIds() {
+ return Arrays.asList("prop1", "prop2");
+ }
+
+ @Override
+ public boolean addItemProperty(Object id, Property property)
+ throws UnsupportedOperationException {
+ return false;
+ }
+
+ @Override
+ public boolean removeItemProperty(Object id)
+ throws UnsupportedOperationException {
+ return false;
+ }
+
+ }
+
+ private static class StringProperty extends AbstractProperty<String> {
+
+ @Override
+ public String getValue() {
+ return null;
+ }
+
+ @Override
+ public void setValue(String newValue)
+ throws Property.ReadOnlyException {
+ }
+
+ @Override
+ public Class<? extends String> getType() {
+ return String.class;
+ }
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java
new file mode 100644
index 0000000000..f14b966a2d
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java
@@ -0,0 +1,51 @@
+package com.vaadin.tests.server.component.fieldgroup;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.tests.data.bean.BeanWithReadOnlyField;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class FieldGroupWithReadOnlyPropertiesTest {
+
+ private LegacyTextField readOnlyField = new LegacyTextField();
+ private LegacyTextField writableField = new LegacyTextField();
+
+ @Test
+ public void bindReadOnlyPropertyToFieldGroup() {
+ BeanWithReadOnlyField bean = new BeanWithReadOnlyField();
+ BeanItem<BeanWithReadOnlyField> beanItem = new BeanItem<BeanWithReadOnlyField>(
+ bean);
+ beanItem.getItemProperty("readOnlyField").setReadOnly(true);
+
+ FieldGroup fieldGroup = new FieldGroup(beanItem);
+ fieldGroup.bindMemberFields(this);
+
+ assertTrue(readOnlyField.isReadOnly());
+ assertFalse(writableField.isReadOnly());
+ }
+
+ @Test
+ public void fieldGroupSetReadOnlyTest() {
+ BeanWithReadOnlyField bean = new BeanWithReadOnlyField();
+ BeanItem<BeanWithReadOnlyField> beanItem = new BeanItem<BeanWithReadOnlyField>(
+ bean);
+ beanItem.getItemProperty("readOnlyField").setReadOnly(true);
+
+ FieldGroup fieldGroup = new FieldGroup(beanItem);
+ fieldGroup.bindMemberFields(this);
+
+ fieldGroup.setReadOnly(true);
+ assertTrue(readOnlyField.isReadOnly());
+ assertTrue(writableField.isReadOnly());
+
+ fieldGroup.setReadOnly(false);
+ assertTrue(readOnlyField.isReadOnly());
+ assertFalse(writableField.isReadOnly());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java
new file mode 100644
index 0000000000..0ef30316ac
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java
@@ -0,0 +1,53 @@
+package com.vaadin.tests.server.component.fieldgroup;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.fieldgroup.PropertyId;
+import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.data.util.PropertysetItem;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class FieldNamedDescriptionTest {
+
+ @Test
+ public void bindReadOnlyPropertyToFieldGroup() {
+ // Create an item
+ PropertysetItem item = new PropertysetItem();
+ item.addItemProperty("name", new ObjectProperty<String>("Zaphod"));
+ item.addItemProperty("description",
+ new ObjectProperty<String>("This is a description"));
+
+ // Define a form as a class that extends some layout
+ class MyForm extends FormLayout {
+ // Member that will bind to the "name" property
+ LegacyTextField name = new LegacyTextField("Name");
+
+ // This member will not bind to the desctiptionProperty as the name
+ // description conflicts with something in the binding process
+ @PropertyId("description")
+ LegacyTextField description = new LegacyTextField("Description");
+
+ public MyForm() {
+
+ // Add the fields
+ addComponent(name);
+ addComponent(description);
+ }
+ }
+
+ // Create one
+ MyForm form = new MyForm();
+
+ // Now create a binder that can also creates the fields
+ // using the default field factory
+ FieldGroup binder = new FieldGroup(item);
+ binder.bindMemberFields(form);
+
+ assertTrue(form.description.getValue().equals("This is a description"));
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java
new file mode 100644
index 0000000000..3bff93c042
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2016 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.LegacyGrid;
+
+public class GridAddRowBuiltinContainerTest {
+ LegacyGrid grid = new LegacyGrid();
+ 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");
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java
new file mode 100644
index 0000000000..f126e636ba
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2016 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 java.util.Iterator;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.LegacyGrid.FooterCell;
+import com.vaadin.ui.LegacyGrid.HeaderCell;
+import com.vaadin.ui.Label;
+
+public class GridChildrenTest {
+
+ @Test
+ public void componentsInMergedHeader() {
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("foo");
+ grid.addColumn("bar");
+ grid.addColumn("baz");
+ HeaderCell merged = grid.getDefaultHeaderRow().join("foo", "bar",
+ "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Iterator<Component> i = grid.iterator();
+ Assert.assertEquals(label, i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+
+ @Test
+ public void componentsInMergedFooter() {
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("foo");
+ grid.addColumn("bar");
+ grid.addColumn("baz");
+ FooterCell merged = grid.addFooterRowAt(0).join("foo", "bar", "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Iterator<Component> i = grid.iterator();
+ Assert.assertEquals(label, i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java
new file mode 100644
index 0000000000..1af2577fa3
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2016 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.IndexedContainer;
+
+public class GridColumnAddingAndRemovingTest {
+
+ LegacyGrid grid = new LegacyGrid();
+ Container.Indexed container;
+
+ @Before
+ public void setUp() {
+ container = grid.getContainerDataSource();
+ container.addItem();
+ }
+
+ @Test
+ public void testAddColumn() {
+ grid.addColumn("foo");
+
+ Property<?> property = container
+ .getContainerProperty(container.firstItemId(), "foo");
+ assertEquals(property.getType(), String.class);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testAddColumnTwice() {
+ grid.addColumn("foo");
+ grid.addColumn("foo");
+ }
+
+ @Test
+ public void testAddRemoveAndAddAgainColumn() {
+ grid.addColumn("foo");
+ grid.removeColumn("foo");
+
+ // Removing a column, doesn't remove the property
+ Property<?> property = container
+ .getContainerProperty(container.firstItemId(), "foo");
+ assertEquals(property.getType(), String.class);
+ grid.addColumn("foo");
+ }
+
+ @Test
+ public void testAddNumberColumns() {
+ grid.addColumn("bar", Integer.class);
+ grid.addColumn("baz", Double.class);
+
+ Property<?> property = container
+ .getContainerProperty(container.firstItemId(), "bar");
+ assertEquals(property.getType(), Integer.class);
+ assertEquals(null, property.getValue());
+ property = container.getContainerProperty(container.firstItemId(),
+ "baz");
+ assertEquals(property.getType(), Double.class);
+ assertEquals(null, property.getValue());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testAddDifferentTypeColumn() {
+ grid.addColumn("foo");
+ grid.removeColumn("foo");
+ grid.addColumn("foo", Integer.class);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testAddColumnToNonDefaultContainer() {
+ grid.setContainerDataSource(new IndexedContainer());
+ grid.addColumn("foo");
+ }
+
+ @Test
+ public void testAddColumnForExistingProperty() {
+ grid.addColumn("bar");
+ IndexedContainer container2 = new IndexedContainer();
+ container2.addContainerProperty("foo", Integer.class, 0);
+ container2.addContainerProperty("bar", String.class, "");
+ grid.setContainerDataSource(container2);
+ assertNull("Grid should not have a column for property foo",
+ grid.getColumn("foo"));
+ assertNotNull("Grid did should have a column for property bar",
+ grid.getColumn("bar"));
+ for (LegacyGrid.Column column : grid.getColumns()) {
+ assertNotNull("Grid getColumns returned a null value", column);
+ }
+
+ grid.removeAllColumns();
+ grid.addColumn("foo");
+ assertNotNull("Grid should now have a column for property foo",
+ grid.getColumn("foo"));
+ assertNull("Grid should not have a column for property bar anymore",
+ grid.getColumn("bar"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testAddIncompatibleColumnProperty() {
+ grid.addColumn("bar");
+ grid.removeAllColumns();
+ grid.addColumn("bar", Integer.class);
+ }
+
+ @Test
+ public void testAddBooleanColumnProperty() {
+ grid.addColumn("foo", Boolean.class);
+ Property<?> property = container
+ .getContainerProperty(container.firstItemId(), "foo");
+ assertEquals(property.getType(), Boolean.class);
+ assertEquals(property.getValue(), null);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java
new file mode 100644
index 0000000000..570e9b92fc
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2000-2016 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 static org.easymock.EasyMock.and;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.isA;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.vaadin.ui.LegacyGrid;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.KeyMapper;
+import com.vaadin.shared.ui.grid.GridColumnState;
+import com.vaadin.shared.ui.grid.GridState;
+import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.LegacyGrid.Column;
+import com.vaadin.ui.LegacyGrid.ColumnResizeEvent;
+import com.vaadin.ui.LegacyGrid.ColumnResizeListener;
+import com.vaadin.v7.ui.LegacyTextField;
+
+public class GridColumnsTest {
+
+ private LegacyGrid grid;
+
+ private GridState state;
+
+ private Method getStateMethod;
+
+ private Field columnIdGeneratorField;
+
+ private KeyMapper<Object> columnIdMapper;
+
+ @Before
+ @SuppressWarnings("unchecked")
+ public void setup() throws Exception {
+ IndexedContainer ds = new IndexedContainer();
+ for (int c = 0; c < 10; c++) {
+ ds.addContainerProperty("column" + c, String.class, "");
+ }
+ ds.addContainerProperty("noSort", Object.class, null);
+ grid = new LegacyGrid(ds);
+
+ getStateMethod = LegacyGrid.class.getDeclaredMethod("getState");
+ getStateMethod.setAccessible(true);
+
+ state = (GridState) getStateMethod.invoke(grid);
+
+ columnIdGeneratorField = LegacyGrid.class.getDeclaredField("columnKeys");
+ columnIdGeneratorField.setAccessible(true);
+
+ columnIdMapper = (KeyMapper<Object>) columnIdGeneratorField.get(grid);
+ }
+
+ @Test
+ public void testColumnGeneration() throws Exception {
+
+ for (Object propertyId : grid.getContainerDataSource()
+ .getContainerPropertyIds()) {
+
+ // All property ids should get a column
+ Column column = grid.getColumn(propertyId);
+ assertNotNull(column);
+
+ // Humanized property id should be the column header by default
+ assertEquals(
+ SharedUtil.camelCaseToHumanFriendly(propertyId.toString()),
+ grid.getDefaultHeaderRow().getCell(propertyId).getText());
+ }
+ }
+
+ @Test
+ public void testModifyingColumnProperties() throws Exception {
+
+ // Modify first column
+ Column column = grid.getColumn("column1");
+ assertNotNull(column);
+
+ column.setHeaderCaption("CustomHeader");
+ assertEquals("CustomHeader", column.getHeaderCaption());
+ assertEquals(column.getHeaderCaption(),
+ grid.getDefaultHeaderRow().getCell("column1").getText());
+
+ column.setWidth(100);
+ assertEquals(100, column.getWidth(), 0.49d);
+ assertEquals(column.getWidth(), getColumnState("column1").width, 0.49d);
+
+ try {
+ column.setWidth(-1);
+ fail("Setting width to -1 should throw exception");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+
+ assertEquals(100, column.getWidth(), 0.49d);
+ assertEquals(100, getColumnState("column1").width, 0.49d);
+ }
+
+ @Test
+ public void testRemovingColumnByRemovingPropertyFromContainer()
+ throws Exception {
+
+ Column column = grid.getColumn("column1");
+ assertNotNull(column);
+
+ // Remove column
+ grid.getContainerDataSource().removeContainerProperty("column1");
+
+ try {
+ column.setHeaderCaption("asd");
+
+ fail("Succeeded in modifying a detached column");
+ } catch (IllegalStateException ise) {
+ // Detached state should throw exception
+ }
+
+ try {
+ column.setWidth(123);
+ fail("Succeeded in modifying a detached column");
+ } catch (IllegalStateException ise) {
+ // Detached state should throw exception
+ }
+
+ assertNull(grid.getColumn("column1"));
+ assertNull(getColumnState("column1"));
+ }
+
+ @Test
+ public void testAddingColumnByAddingPropertyToContainer() throws Exception {
+ grid.getContainerDataSource().addContainerProperty("columnX",
+ String.class, "");
+ Column column = grid.getColumn("columnX");
+ assertNotNull(column);
+ }
+
+ @Test
+ public void testHeaderVisiblility() throws Exception {
+
+ assertTrue(grid.isHeaderVisible());
+ assertTrue(state.header.visible);
+
+ grid.setHeaderVisible(false);
+ assertFalse(grid.isHeaderVisible());
+ assertFalse(state.header.visible);
+
+ grid.setHeaderVisible(true);
+ assertTrue(grid.isHeaderVisible());
+ assertTrue(state.header.visible);
+ }
+
+ @Test
+ public void testFooterVisibility() throws Exception {
+
+ assertTrue(grid.isFooterVisible());
+ assertTrue(state.footer.visible);
+
+ grid.setFooterVisible(false);
+ assertFalse(grid.isFooterVisible());
+ assertFalse(state.footer.visible);
+
+ grid.setFooterVisible(true);
+ assertTrue(grid.isFooterVisible());
+ assertTrue(state.footer.visible);
+ }
+
+ @Test
+ public void testSetFrozenColumnCount() {
+ assertEquals("Grid should not start with a frozen column", 0,
+ grid.getFrozenColumnCount());
+ grid.setFrozenColumnCount(2);
+ assertEquals("Freezing two columns should freeze two columns", 2,
+ grid.getFrozenColumnCount());
+ }
+
+ @Test
+ public void testSetFrozenColumnCountThroughColumn() {
+ assertEquals("Grid should not start with a frozen column", 0,
+ grid.getFrozenColumnCount());
+ grid.getColumns().get(2).setLastFrozenColumn();
+ assertEquals(
+ "Setting the third column as last frozen should freeze three columns",
+ 3, grid.getFrozenColumnCount());
+ }
+
+ @Test
+ public void testFrozenColumnRemoveColumn() {
+ assertEquals("Grid should not start with a frozen column", 0,
+ grid.getFrozenColumnCount());
+
+ int containerSize = grid.getContainerDataSource()
+ .getContainerPropertyIds().size();
+ grid.setFrozenColumnCount(containerSize);
+
+ Object propertyId = grid.getContainerDataSource()
+ .getContainerPropertyIds().iterator().next();
+
+ grid.getContainerDataSource().removeContainerProperty(propertyId);
+ assertEquals("Frozen column count should update when removing last row",
+ containerSize - 1, grid.getFrozenColumnCount());
+ }
+
+ @Test
+ public void testReorderColumns() {
+ Set<?> containerProperties = new LinkedHashSet<Object>(
+ grid.getContainerDataSource().getContainerPropertyIds());
+ Object[] properties = new Object[] { "column3", "column2", "column6" };
+ grid.setColumnOrder(properties);
+
+ int i = 0;
+ // Test sorted columns are first in order
+ for (Object property : properties) {
+ containerProperties.remove(property);
+ assertEquals(columnIdMapper.key(property),
+ state.columnOrder.get(i++));
+ }
+
+ // Test remaining columns are in original order
+ for (Object property : containerProperties) {
+ assertEquals(columnIdMapper.key(property),
+ state.columnOrder.get(i++));
+ }
+
+ try {
+ grid.setColumnOrder("foo", "bar", "baz");
+ fail("Grid allowed sorting with non-existent properties");
+ } catch (IllegalArgumentException e) {
+ // All ok
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRemoveColumnThatDoesNotExist() {
+ grid.removeColumn("banana phone");
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testSetNonSortableColumnSortable() {
+ Column noSortColumn = grid.getColumn("noSort");
+ assertFalse("Object property column should not be sortable.",
+ noSortColumn.isSortable());
+ noSortColumn.setSortable(true);
+ }
+
+ @Test
+ public void testColumnsEditableByDefault() {
+ for (Column c : grid.getColumns()) {
+ assertTrue(c + " should be editable", c.isEditable());
+ }
+ }
+
+ @Test
+ public void testPropertyAndColumnEditorFieldsMatch() {
+ Column column1 = grid.getColumn("column1");
+ column1.setEditorField(new LegacyTextField());
+ assertSame(column1.getEditorField(),
+ grid.getColumn("column1").getEditorField());
+
+ Column column2 = grid.getColumn("column2");
+ column2.setEditorField(new LegacyTextField());
+ assertSame(column2.getEditorField(), column2.getEditorField());
+ }
+
+ @Test
+ public void testUneditableColumnHasNoField() {
+ Column col = grid.getColumn("column1");
+
+ col.setEditable(false);
+
+ assertFalse("Column should be uneditable", col.isEditable());
+ assertNull("Uneditable column should not be auto-assigned a Field",
+ col.getEditorField());
+ }
+
+ private GridColumnState getColumnState(Object propertyId) {
+ String columnId = columnIdMapper.key(propertyId);
+ for (GridColumnState columnState : state.columns) {
+ if (columnState.id.equals(columnId)) {
+ return columnState;
+ }
+ }
+ return null;
+ }
+
+ @Test
+ public void testAddAndRemoveSortableColumn() {
+ boolean sortable = grid.getColumn("column1").isSortable();
+ grid.removeColumn("column1");
+ grid.addColumn("column1");
+ assertEquals("Column sortability changed when re-adding", sortable,
+ grid.getColumn("column1").isSortable());
+ }
+
+ @Test
+ public void testSetColumns() {
+ grid.setColumns("column7", "column0", "column9");
+ Iterator<Column> it = grid.getColumns().iterator();
+ assertEquals(it.next().getPropertyId(), "column7");
+ assertEquals(it.next().getPropertyId(), "column0");
+ assertEquals(it.next().getPropertyId(), "column9");
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testAddingColumnsWithSetColumns() {
+ LegacyGrid g = new LegacyGrid();
+ g.setColumns("c1", "c2", "c3");
+ Iterator<Column> it = g.getColumns().iterator();
+ assertEquals(it.next().getPropertyId(), "c1");
+ assertEquals(it.next().getPropertyId(), "c2");
+ assertEquals(it.next().getPropertyId(), "c3");
+ assertFalse(it.hasNext());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testAddingColumnsWithSetColumnsNonDefaultContainer() {
+ grid.setColumns("column1", "column2", "column50");
+ }
+
+ @Test
+ public void testDefaultColumnHidingToggleCaption() {
+ Column firstColumn = grid.getColumns().get(0);
+ firstColumn.setHeaderCaption("headerCaption");
+ assertEquals(null, firstColumn.getHidingToggleCaption());
+ }
+
+ @Test
+ public void testOverriddenColumnHidingToggleCaption() {
+ Column firstColumn = grid.getColumns().get(0);
+ firstColumn.setHidingToggleCaption("hidingToggleCaption");
+ firstColumn.setHeaderCaption("headerCaption");
+ assertEquals("hidingToggleCaption",
+ firstColumn.getHidingToggleCaption());
+ }
+
+ @Test
+ public void testColumnSetWidthFiresResizeEvent() {
+ final Column firstColumn = grid.getColumns().get(0);
+
+ // prepare a listener mock that captures the argument
+ ColumnResizeListener mock = EasyMock
+ .createMock(ColumnResizeListener.class);
+ Capture<ColumnResizeEvent> capturedEvent = new Capture<ColumnResizeEvent>();
+ mock.columnResize(
+ and(capture(capturedEvent), isA(ColumnResizeEvent.class)));
+ EasyMock.expectLastCall().once();
+
+ // Tell it to wait for the call
+ EasyMock.replay(mock);
+
+ // Cause a resize event
+ grid.addColumnResizeListener(mock);
+ firstColumn.setWidth(firstColumn.getWidth() + 10);
+
+ // Verify the method was called
+ EasyMock.verify(mock);
+
+ // Asserts on the captured event
+ ColumnResizeEvent event = capturedEvent.getValue();
+ assertEquals("Event column was not first column.", firstColumn,
+ event.getColumn());
+ assertFalse("Event should not be userOriginated",
+ event.isUserOriginated());
+ }
+
+ @Test
+ public void textHeaderCaptionIsReturned() {
+ Column firstColumn = grid.getColumns().get(0);
+
+ firstColumn.setHeaderCaption("text");
+
+ assertThat(firstColumn.getHeaderCaption(), is("text"));
+ }
+
+ @Test
+ public void defaultCaptionIsReturnedForHtml() {
+ Column firstColumn = grid.getColumns().get(0);
+
+ grid.getDefaultHeaderRow().getCell("column0").setHtml("<b>html</b>");
+
+ assertThat(firstColumn.getHeaderCaption(), is("Column0"));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java
new file mode 100644
index 0000000000..fa6c57df93
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2016 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 static org.junit.Assert.assertFalse;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Test;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.AbstractInMemoryContainer;
+import com.vaadin.ui.LegacyGrid.Column;
+
+public class GridContainerNotSortableTest {
+
+ final AbstractInMemoryContainer<Object, Object, Item> notSortableDataSource = new AbstractInMemoryContainer<Object, Object, Item>() {
+
+ private Map<Object, Property<?>> properties = new LinkedHashMap<Object, Property<?>>();
+
+ {
+ properties.put("Foo", new Property<String>() {
+
+ @Override
+ public String getValue() {
+ return "foo";
+ }
+
+ @Override
+ public void setValue(String newValue) throws ReadOnlyException {
+ throw new ReadOnlyException();
+ }
+
+ @Override
+ public Class<? extends String> getType() {
+ return String.class;
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ @Override
+ public void setReadOnly(boolean newStatus) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ }
+
+ @Override
+ public Collection<?> getContainerPropertyIds() {
+ return properties.keySet();
+ }
+
+ @Override
+ public Property getContainerProperty(Object itemId, Object propertyId) {
+ return properties.get(propertyId);
+ }
+
+ @Override
+ public Class<?> getType(Object propertyId) {
+ return properties.get(propertyId).getType();
+ }
+
+ @Override
+ protected Item getUnfilteredItem(Object itemId) {
+ return null;
+ }
+ };
+
+ @Test
+ public void testGridWithNotSortableContainer() {
+ new LegacyGrid(notSortableDataSource);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNotSortableGridSetColumnSortable() {
+ LegacyGrid grid = new LegacyGrid();
+ grid.setContainerDataSource(notSortableDataSource);
+ Column column = grid.getColumn("Foo");
+ assertFalse("Column should not be sortable initially.",
+ column.isSortable());
+ column.setSortable(true);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java
new file mode 100644
index 0000000000..7b07aefcb2
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000-2016 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 java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.LegacyGrid.DetailsGenerator;
+import com.vaadin.ui.LegacyGrid.RowReference;
+import com.vaadin.ui.Label;
+
+public class GridContainerTest {
+
+ /**
+ * Null Stream used with serialization tests
+ */
+ protected static OutputStream NULLSTREAM = new OutputStream() {
+ @Override
+ public void write(int b) {
+ }
+ };
+
+ @Test
+ public void testDetailsGeneratorDoesNotResetOnContainerChange() {
+ LegacyGrid grid = new LegacyGrid();
+ DetailsGenerator detGen = new DetailsGenerator() {
+
+ @Override
+ public Component getDetails(RowReference rowReference) {
+ return new Label("Empty details");
+ }
+ };
+ grid.setDetailsGenerator(detGen);
+
+ grid.setContainerDataSource(createContainer());
+
+ Assert.assertEquals("DetailsGenerator changed", detGen,
+ grid.getDetailsGenerator());
+ }
+
+ @Test
+ public void testSetContainerTwice() throws Exception {
+
+ TestGrid grid = new TestGrid();
+
+ grid.setContainerDataSource(createContainer());
+
+ // Simulate initial response to ensure "lazy" state changes are done
+ // before resetting the datasource
+ grid.beforeClientResponse(true);
+ grid.getDataProvider().beforeClientResponse(true);
+
+ grid.setContainerDataSource(createContainer());
+ }
+
+ @SuppressWarnings("unchecked")
+ private IndexedContainer createContainer() {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty("x", String.class, null);
+ container.addItem(0).getItemProperty("x").setValue("y");
+ return container;
+ }
+
+ @Test
+ public void setColumnsOrder() {
+ LegacyGrid grid = new LegacyGrid();
+ IndexedContainer ic = new IndexedContainer();
+ ic.addContainerProperty("foo", String.class, "");
+ ic.addContainerProperty("baz", String.class, "");
+ ic.addContainerProperty("bar", String.class, "");
+ grid.setContainerDataSource(ic);
+ grid.setColumns("foo", "baz", "bar");
+
+ Assert.assertEquals("foo", grid.getColumns().get(0).getPropertyId());
+ Assert.assertEquals("baz", grid.getColumns().get(1).getPropertyId());
+ Assert.assertEquals("bar", grid.getColumns().get(2).getPropertyId());
+ }
+
+ @Test
+ public void addColumnNotInContainer() {
+ LegacyGrid grid = new LegacyGrid();
+ grid.setContainerDataSource(new IndexedContainer());
+ try {
+ grid.addColumn("notInContainer");
+ Assert.fail(
+ "Adding a property id not in the container should throw an exception");
+ } catch (IllegalStateException e) {
+ Assert.assertTrue(e.getMessage().contains("notInContainer"));
+ Assert.assertTrue(
+ e.getMessage().contains("does not exist in the container"));
+ }
+ }
+
+ @Test
+ public void setColumnsForPropertyIdNotInContainer() {
+ LegacyGrid grid = new LegacyGrid();
+ grid.setContainerDataSource(new IndexedContainer());
+ try {
+ grid.setColumns("notInContainer", "notThereEither");
+ Assert.fail(
+ "Setting columns for property ids not in the container should throw an exception");
+ } catch (IllegalStateException e) {
+ // addColumn is run in random order..
+ Assert.assertTrue(e.getMessage().contains("notInContainer")
+ || e.getMessage().contains("notThereEither"));
+ Assert.assertTrue(
+ e.getMessage().contains("does not exist in the container"));
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void multipleAddColumnsForDefaultContainer() {
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("foo");
+ grid.addColumn("foo");
+ }
+
+ @Test
+ public void testSerializeRpcDataProviderWithRowChanges()
+ throws IOException {
+ LegacyGrid grid = new LegacyGrid();
+ IndexedContainer container = new IndexedContainer();
+ grid.setContainerDataSource(container);
+ container.addItem();
+ serializeComponent(grid);
+ }
+
+ protected void serializeComponent(Component component) throws IOException {
+ ObjectOutputStream stream = null;
+ try {
+ stream = new ObjectOutputStream(NULLSTREAM);
+ stream.writeObject(component);
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java
new file mode 100644
index 0000000000..15daa264d9
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2000-2016 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Method;
+
+import com.vaadin.ui.LegacyGrid;
+import com.vaadin.v7.ui.LegacyField;
+import com.vaadin.v7.ui.LegacyTextField;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.MockVaadinSession;
+import com.vaadin.server.VaadinService;
+import com.vaadin.server.VaadinSession;
+
+public class GridEditorTest {
+
+ private static final Object PROPERTY_NAME = "name";
+ private static final Object PROPERTY_AGE = "age";
+ private static final String DEFAULT_NAME = "Some Valid Name";
+ private static final Integer DEFAULT_AGE = 25;
+ private static final Object ITEM_ID = new Object();
+
+ // Explicit field for the test session to save it from GC
+ private VaadinSession session;
+
+ private final LegacyGrid grid = new LegacyGrid();
+ private Method doEditMethod;
+
+ @Before
+ @SuppressWarnings("unchecked")
+ public void setup() throws SecurityException, NoSuchMethodException {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty(PROPERTY_NAME, String.class, "[name]");
+ container.addContainerProperty(PROPERTY_AGE, Integer.class,
+ Integer.valueOf(-1));
+
+ Item item = container.addItem(ITEM_ID);
+ item.getItemProperty(PROPERTY_NAME).setValue(DEFAULT_NAME);
+ item.getItemProperty(PROPERTY_AGE).setValue(DEFAULT_AGE);
+ grid.setContainerDataSource(container);
+
+ // VaadinSession needed for ConverterFactory
+ VaadinService mockService = EasyMock
+ .createNiceMock(VaadinService.class);
+ session = new MockVaadinSession(mockService);
+ VaadinSession.setCurrent(session);
+ session.lock();
+
+ // Access to method for actual editing.
+ doEditMethod = LegacyGrid.class.getDeclaredMethod("doEditItem");
+ doEditMethod.setAccessible(true);
+ }
+
+ @After
+ public void tearDown() {
+ session.unlock();
+ session = null;
+ VaadinSession.setCurrent(null);
+ }
+
+ @Test
+ public void testInitAssumptions() throws Exception {
+ assertFalse(grid.isEditorEnabled());
+ assertNull(grid.getEditedItemId());
+ assertNotNull(grid.getEditorFieldGroup());
+ }
+
+ @Test
+ public void testSetEnabled() throws Exception {
+ assertFalse(grid.isEditorEnabled());
+ grid.setEditorEnabled(true);
+ assertTrue(grid.isEditorEnabled());
+ }
+
+ @Test
+ public void testSetDisabled() throws Exception {
+ assertFalse(grid.isEditorEnabled());
+ grid.setEditorEnabled(true);
+ grid.setEditorEnabled(false);
+ assertFalse(grid.isEditorEnabled());
+ }
+
+ @Test
+ public void testSetReEnabled() throws Exception {
+ assertFalse(grid.isEditorEnabled());
+ grid.setEditorEnabled(true);
+ grid.setEditorEnabled(false);
+ grid.setEditorEnabled(true);
+ assertTrue(grid.isEditorEnabled());
+ }
+
+ @Test
+ public void testDetached() throws Exception {
+ FieldGroup oldFieldGroup = grid.getEditorFieldGroup();
+ grid.removeAllColumns();
+ grid.setContainerDataSource(new IndexedContainer());
+ assertFalse(oldFieldGroup == grid.getEditorFieldGroup());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testDisabledEditItem() throws Exception {
+ grid.editItem(ITEM_ID);
+ }
+
+ @Test
+ public void testEditItem() throws Exception {
+ startEdit();
+ assertEquals(ITEM_ID, grid.getEditedItemId());
+ assertEquals(getEditedItem(),
+ grid.getEditorFieldGroup().getItemDataSource());
+
+ assertEquals(DEFAULT_NAME,
+ grid.getColumn(PROPERTY_NAME).getEditorField().getValue());
+ assertEquals(String.valueOf(DEFAULT_AGE),
+ grid.getColumn(PROPERTY_AGE).getEditorField().getValue());
+ }
+
+ @Test
+ public void testSaveEditor() throws Exception {
+ startEdit();
+ LegacyTextField field = (LegacyTextField) grid.getColumn(PROPERTY_NAME)
+ .getEditorField();
+
+ field.setValue("New Name");
+ assertEquals(DEFAULT_NAME, field.getPropertyDataSource().getValue());
+
+ grid.saveEditor();
+ assertTrue(grid.isEditorActive());
+ assertFalse(field.isModified());
+ assertEquals("New Name", field.getValue());
+ assertEquals("New Name", getEditedProperty(PROPERTY_NAME).getValue());
+ }
+
+ @Test
+ public void testSaveEditorCommitFail() throws Exception {
+ startEdit();
+
+ ((LegacyTextField) grid.getColumn(PROPERTY_AGE).getEditorField())
+ .setValue("Invalid");
+ try {
+ // Manual fail instead of @Test(expected=...) to check it is
+ // saveEditor that fails and not setValue
+ grid.saveEditor();
+ Assert.fail(
+ "CommitException expected when saving an invalid field value");
+ } catch (CommitException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testCancelEditor() throws Exception {
+ startEdit();
+ LegacyTextField field = (LegacyTextField) grid.getColumn(PROPERTY_NAME)
+ .getEditorField();
+ field.setValue("New Name");
+
+ Property<?> datasource = field.getPropertyDataSource();
+
+ grid.cancelEditor();
+ assertFalse(grid.isEditorActive());
+ assertNull(grid.getEditedItemId());
+ assertFalse(field.isModified());
+ assertEquals("", field.getValue());
+ assertEquals(DEFAULT_NAME, datasource.getValue());
+ assertNull(field.getPropertyDataSource());
+ assertNull(grid.getEditorFieldGroup().getItemDataSource());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNonexistentEditItem() throws Exception {
+ grid.setEditorEnabled(true);
+ grid.editItem(new Object());
+ }
+
+ @Test
+ public void testGetField() throws Exception {
+ startEdit();
+
+ assertNotNull(grid.getColumn(PROPERTY_NAME).getEditorField());
+ }
+
+ @Test
+ public void testGetFieldWithoutItem() throws Exception {
+ grid.setEditorEnabled(true);
+ assertNotNull(grid.getColumn(PROPERTY_NAME).getEditorField());
+ }
+
+ @Test
+ public void testCustomBinding() {
+ LegacyTextField textField = new LegacyTextField();
+ grid.getColumn(PROPERTY_NAME).setEditorField(textField);
+
+ startEdit();
+
+ assertSame(textField, grid.getColumn(PROPERTY_NAME).getEditorField());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testDisableWhileEditing() {
+ startEdit();
+ grid.setEditorEnabled(false);
+ }
+
+ @Test
+ public void testFieldIsNotReadonly() {
+ startEdit();
+
+ LegacyField<?> field = grid.getColumn(PROPERTY_NAME).getEditorField();
+ assertFalse(field.isReadOnly());
+ }
+
+ @Test
+ public void testFieldIsReadonlyWhenFieldGroupIsReadonly() {
+ startEdit();
+
+ grid.getEditorFieldGroup().setReadOnly(true);
+ LegacyField<?> field = grid.getColumn(PROPERTY_NAME).getEditorField();
+ assertTrue(field.isReadOnly());
+ }
+
+ @Test
+ public void testColumnRemoved() {
+ LegacyField<?> field = grid.getColumn(PROPERTY_NAME).getEditorField();
+
+ assertSame("field should be attached to ", grid, field.getParent());
+
+ grid.removeColumn(PROPERTY_NAME);
+
+ assertNull("field should be detached from ", field.getParent());
+ }
+
+ @Test
+ public void testSetFieldAgain() {
+ LegacyTextField field = new LegacyTextField();
+ grid.getColumn(PROPERTY_NAME).setEditorField(field);
+
+ field = new LegacyTextField();
+ grid.getColumn(PROPERTY_NAME).setEditorField(field);
+
+ assertSame("new field should be used.", field,
+ grid.getColumn(PROPERTY_NAME).getEditorField());
+ }
+
+ private void startEdit() {
+ grid.setEditorEnabled(true);
+ grid.editItem(ITEM_ID);
+ // Simulate succesful client response to actually start the editing.
+ try {
+ doEditMethod.invoke(grid);
+ } catch (Exception e) {
+ Assert.fail("Editing item " + ITEM_ID + " failed. Cause: "
+ + e.getCause().toString());
+ }
+ }
+
+ private Item getEditedItem() {
+ assertNotNull(grid.getEditedItemId());
+ return grid.getContainerDataSource().getItem(grid.getEditedItemId());
+ }
+
+ private Property<?> getEditedProperty(Object propertyId) {
+ return getEditedItem().getItemProperty(PROPERTY_NAME);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java
new file mode 100644
index 0000000000..452d2713a4
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2016 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 static org.junit.Assert.assertTrue;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Test;
+
+import com.vaadin.ui.LegacyGrid.AbstractGridExtension;
+
+public class GridExtensionTest {
+
+ public static class DummyGridExtension extends AbstractGridExtension {
+
+ public DummyGridExtension(LegacyGrid grid) {
+ super(grid);
+ }
+ }
+
+ @Test
+ public void testCreateExtension() {
+ LegacyGrid grid = new LegacyGrid();
+ DummyGridExtension dummy = new DummyGridExtension(grid);
+ assertTrue("DummyGridExtension never made it to Grid",
+ grid.getExtensions().contains(dummy));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java
new file mode 100644
index 0000000000..7e910d2428
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2000-2013 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.SelectionEvent;
+import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.ui.LegacyGrid.SelectionMode;
+import com.vaadin.ui.LegacyGrid.SelectionModel;
+
+public class GridSelectionTest {
+
+ private static class MockSelectionChangeListener
+ implements SelectionListener {
+ private SelectionEvent event;
+
+ @Override
+ public void select(final SelectionEvent event) {
+ this.event = event;
+ }
+
+ public Collection<?> getAdded() {
+ return event.getAdded();
+ }
+
+ public Collection<?> getRemoved() {
+ return event.getRemoved();
+ }
+
+ public void clearEvent() {
+ /*
+ * This method is not strictly needed as the event will simply be
+ * overridden, but it's good practice, and makes the code more
+ * obvious.
+ */
+ event = null;
+ }
+
+ public boolean eventHasHappened() {
+ return event != null;
+ }
+ }
+
+ private LegacyGrid grid;
+ private MockSelectionChangeListener mockListener;
+
+ private final Object itemId1Present = "itemId1Present";
+ private final Object itemId2Present = "itemId2Present";
+
+ private final Object itemId1NotPresent = "itemId1NotPresent";
+ private final Object itemId2NotPresent = "itemId2NotPresent";
+
+ @Before
+ public void setup() {
+ final IndexedContainer container = new IndexedContainer();
+ container.addItem(itemId1Present);
+ container.addItem(itemId2Present);
+ for (int i = 2; i < 10; i++) {
+ container.addItem(new Object());
+ }
+
+ assertEquals("init size", 10, container.size());
+ assertTrue("itemId1Present", container.containsId(itemId1Present));
+ assertTrue("itemId2Present", container.containsId(itemId2Present));
+ assertFalse("itemId1NotPresent",
+ container.containsId(itemId1NotPresent));
+ assertFalse("itemId2NotPresent",
+ container.containsId(itemId2NotPresent));
+
+ grid = new LegacyGrid(container);
+
+ mockListener = new MockSelectionChangeListener();
+ grid.addSelectionListener(mockListener);
+
+ assertFalse("eventHasHappened", mockListener.eventHasHappened());
+ }
+
+ @Test
+ public void defaultSelectionModeIsSingle() {
+ assertTrue(grid.getSelectionModel() instanceof SelectionModel.Single);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void getSelectedRowThrowsExceptionMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ grid.getSelectedRow();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void getSelectedRowThrowsExceptionNone() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.getSelectedRow();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void selectThrowsExceptionNone() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.select(itemId1Present);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void deselectRowThrowsExceptionNone() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.deselect(itemId1Present);
+ }
+
+ @Test
+ public void selectionModeMapsToMulti() {
+ assertTrue(grid.setSelectionMode(
+ SelectionMode.MULTI) instanceof SelectionModel.Multi);
+ }
+
+ @Test
+ public void selectionModeMapsToSingle() {
+ assertTrue(grid.setSelectionMode(
+ SelectionMode.SINGLE) instanceof SelectionModel.Single);
+ }
+
+ @Test
+ public void selectionModeMapsToNone() {
+ assertTrue(grid.setSelectionMode(
+ SelectionMode.NONE) instanceof SelectionModel.None);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void selectionModeNullThrowsException() {
+ grid.setSelectionMode(null);
+ }
+
+ @Test
+ public void noSelectModel_isSelected() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ assertFalse("itemId1Present", grid.isSelected(itemId1Present));
+ assertFalse("itemId1NotPresent", grid.isSelected(itemId1NotPresent));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void noSelectModel_getSelectedRow() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.getSelectedRow();
+ }
+
+ @Test
+ public void noSelectModel_getSelectedRows() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ assertTrue(grid.getSelectedRows().isEmpty());
+ }
+
+ @Test
+ public void selectionCallsListenerMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ selectionCallsListener();
+ }
+
+ @Test
+ public void selectionCallsListenerSingle() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ selectionCallsListener();
+ }
+
+ private void selectionCallsListener() {
+ grid.select(itemId1Present);
+ assertEquals("added size", 1, mockListener.getAdded().size());
+ assertEquals("added item", itemId1Present,
+ mockListener.getAdded().iterator().next());
+ assertEquals("removed size", 0, mockListener.getRemoved().size());
+ }
+
+ @Test
+ public void deselectionCallsListenerMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ deselectionCallsListener();
+ }
+
+ @Test
+ public void deselectionCallsListenerSingle() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ deselectionCallsListener();
+ }
+
+ private void deselectionCallsListener() {
+ grid.select(itemId1Present);
+ mockListener.clearEvent();
+
+ grid.deselect(itemId1Present);
+ assertEquals("removed size", 1, mockListener.getRemoved().size());
+ assertEquals("removed item", itemId1Present,
+ mockListener.getRemoved().iterator().next());
+ assertEquals("removed size", 0, mockListener.getAdded().size());
+ }
+
+ @Test
+ public void deselectPresentButNotSelectedItemIdShouldntFireListenerMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ deselectPresentButNotSelectedItemIdShouldntFireListener();
+ }
+
+ @Test
+ public void deselectPresentButNotSelectedItemIdShouldntFireListenerSingle() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ deselectPresentButNotSelectedItemIdShouldntFireListener();
+ }
+
+ private void deselectPresentButNotSelectedItemIdShouldntFireListener() {
+ grid.deselect(itemId1Present);
+ assertFalse(mockListener.eventHasHappened());
+ }
+
+ @Test
+ public void deselectNotPresentItemIdShouldNotThrowExceptionMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ grid.deselect(itemId1NotPresent);
+ }
+
+ @Test
+ public void deselectNotPresentItemIdShouldNotThrowExceptionSingle() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ grid.deselect(itemId1NotPresent);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void selectNotPresentItemIdShouldThrowExceptionMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ grid.select(itemId1NotPresent);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void selectNotPresentItemIdShouldThrowExceptionSingle() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ grid.select(itemId1NotPresent);
+ }
+
+ @Test
+ public void selectAllMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ final SelectionModel.Multi select = (SelectionModel.Multi) grid
+ .getSelectionModel();
+ select.selectAll();
+ assertEquals("added size", 10, mockListener.getAdded().size());
+ assertEquals("removed size", 0, mockListener.getRemoved().size());
+ assertTrue("itemId1Present",
+ mockListener.getAdded().contains(itemId1Present));
+ assertTrue("itemId2Present",
+ mockListener.getAdded().contains(itemId2Present));
+ }
+
+ @Test
+ public void deselectAllMulti() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ final SelectionModel.Multi select = (SelectionModel.Multi) grid
+ .getSelectionModel();
+ select.selectAll();
+ mockListener.clearEvent();
+
+ select.deselectAll();
+ assertEquals("removed size", 10, mockListener.getRemoved().size());
+ assertEquals("added size", 0, mockListener.getAdded().size());
+ assertTrue("itemId1Present",
+ mockListener.getRemoved().contains(itemId1Present));
+ assertTrue("itemId2Present",
+ mockListener.getRemoved().contains(itemId2Present));
+ assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty());
+ }
+
+ @Test
+ public void gridDeselectAllMultiAllSelected() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ final SelectionModel.Multi select = (SelectionModel.Multi) grid
+ .getSelectionModel();
+ select.selectAll();
+ mockListener.clearEvent();
+
+ assertTrue(grid.deselectAll());
+ assertEquals("removed size", 10, mockListener.getRemoved().size());
+ assertEquals("added size", 0, mockListener.getAdded().size());
+ assertTrue("itemId1Present",
+ mockListener.getRemoved().contains(itemId1Present));
+ assertTrue("itemId2Present",
+ mockListener.getRemoved().contains(itemId2Present));
+ assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty());
+
+ }
+
+ @Test
+ public void gridDeselectAllMultiOneSelected() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ final SelectionModel.Multi select = (SelectionModel.Multi) grid
+ .getSelectionModel();
+ select.select(itemId2Present);
+ mockListener.clearEvent();
+
+ assertTrue(grid.deselectAll());
+ assertEquals("removed size", 1, mockListener.getRemoved().size());
+ assertEquals("added size", 0, mockListener.getAdded().size());
+ assertFalse("itemId1Present",
+ mockListener.getRemoved().contains(itemId1Present));
+ assertTrue("itemId2Present",
+ mockListener.getRemoved().contains(itemId2Present));
+ assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty());
+
+ }
+
+ @Test
+ public void gridDeselectAllSingleNoneSelected() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ assertFalse(grid.deselectAll());
+ assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty());
+ }
+
+ @Test
+ public void gridDeselectAllSingleOneSelected() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ final SelectionModel.Single select = (SelectionModel.Single) grid
+ .getSelectionModel();
+ select.select(itemId2Present);
+ mockListener.clearEvent();
+
+ assertTrue(grid.deselectAll());
+ assertEquals("removed size", 1, mockListener.getRemoved().size());
+ assertEquals("added size", 0, mockListener.getAdded().size());
+ assertFalse("itemId1Present",
+ mockListener.getRemoved().contains(itemId1Present));
+ assertTrue("itemId2Present",
+ mockListener.getRemoved().contains(itemId2Present));
+ assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty());
+
+ }
+
+ @Test
+ public void gridDeselectAllMultiNoneSelected() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+
+ assertFalse(grid.deselectAll());
+ assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty());
+
+ }
+
+ @Test
+ public void reselectionDeselectsPreviousSingle() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ grid.select(itemId1Present);
+ mockListener.clearEvent();
+
+ grid.select(itemId2Present);
+ assertEquals("added size", 1, mockListener.getAdded().size());
+ assertEquals("removed size", 1, mockListener.getRemoved().size());
+ assertEquals("added item", itemId2Present,
+ mockListener.getAdded().iterator().next());
+ assertEquals("removed item", itemId1Present,
+ mockListener.getRemoved().iterator().next());
+ assertEquals("selectedRows is correct", itemId2Present,
+ grid.getSelectedRow());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java
new file mode 100644
index 0000000000..9f5f67d8be
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2016 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.Test;
+
+import com.vaadin.shared.ui.grid.GridState;
+import com.vaadin.ui.LegacyGrid;
+
+/**
+ * Tests for Grid State.
+ *
+ */
+public class GridStateTest {
+
+ @Test
+ public void getPrimaryStyleName_gridHasCustomPrimaryStyleName() {
+ LegacyGrid grid = new LegacyGrid();
+ GridState state = new GridState();
+ Assert.assertEquals("Unexpected primary style name",
+ state.primaryStyleName, grid.getPrimaryStyleName());
+ }
+
+ @Test
+ public void gridStateHasCustomPrimaryStyleName() {
+ GridState state = new GridState();
+ Assert.assertEquals("Unexpected primary style name", "v-grid",
+ state.primaryStyleName);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java
new file mode 100644
index 0000000000..7a8209d50b
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2016 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.lang.reflect.Method;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.data.util.IndexedContainer;
+
+public class GridStaticSectionTest extends LegacyGrid {
+
+ private Indexed dataSource = new IndexedContainer();
+
+ @Before
+ public void setUp() {
+ dataSource.addContainerProperty("firstName", String.class, "");
+ dataSource.addContainerProperty("lastName", String.class, "");
+ dataSource.addContainerProperty("streetAddress", String.class, "");
+ dataSource.addContainerProperty("zipCode", Integer.class, null);
+ setContainerDataSource(dataSource);
+ }
+
+ @Test
+ public void testAddAndRemoveHeaders() {
+ assertEquals(1, getHeaderRowCount());
+ prependHeaderRow();
+ assertEquals(2, getHeaderRowCount());
+ removeHeaderRow(0);
+ assertEquals(1, getHeaderRowCount());
+ removeHeaderRow(0);
+ assertEquals(0, getHeaderRowCount());
+ assertEquals(null, getDefaultHeaderRow());
+ HeaderRow row = appendHeaderRow();
+ assertEquals(1, getHeaderRowCount());
+ assertEquals(null, getDefaultHeaderRow());
+ setDefaultHeaderRow(row);
+ assertEquals(row, getDefaultHeaderRow());
+ }
+
+ @Test
+ public void testAddAndRemoveFooters() {
+ // By default there are no footer rows
+ assertEquals(0, getFooterRowCount());
+ FooterRow row = appendFooterRow();
+
+ assertEquals(1, getFooterRowCount());
+ prependFooterRow();
+ assertEquals(2, getFooterRowCount());
+ assertEquals(row, getFooterRow(1));
+ removeFooterRow(0);
+ assertEquals(1, getFooterRowCount());
+ removeFooterRow(0);
+ assertEquals(0, getFooterRowCount());
+ }
+
+ @Test
+ public void testUnusedPropertyNotInCells() {
+ removeColumn("firstName");
+ assertNull("firstName cell was not removed from existing row",
+ getDefaultHeaderRow().getCell("firstName"));
+ HeaderRow newRow = appendHeaderRow();
+ assertNull("firstName cell was created when it should not.",
+ newRow.getCell("firstName"));
+ addColumn("firstName");
+ assertNotNull(
+ "firstName cell was not created for default row when added again",
+ getDefaultHeaderRow().getCell("firstName"));
+ assertNotNull(
+ "firstName cell was not created for new row when added again",
+ newRow.getCell("firstName"));
+
+ }
+
+ @Test
+ public void testJoinHeaderCells() {
+ HeaderRow mergeRow = prependHeaderRow();
+ mergeRow.join("firstName", "lastName").setText("Name");
+ mergeRow.join(mergeRow.getCell("streetAddress"),
+ mergeRow.getCell("zipCode"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testJoinHeaderCellsIncorrectly() throws Throwable {
+ HeaderRow mergeRow = prependHeaderRow();
+ mergeRow.join("firstName", "zipCode").setText("Name");
+ sanityCheck();
+ }
+
+ @Test
+ public void testJoinAllFooterCells() {
+ FooterRow mergeRow = prependFooterRow();
+ mergeRow.join(dataSource.getContainerPropertyIds().toArray())
+ .setText("All the stuff.");
+ }
+
+ private void sanityCheck() throws Throwable {
+ Method sanityCheckHeader;
+ try {
+ sanityCheckHeader = LegacyGrid.Header.class
+ .getDeclaredMethod("sanityCheck");
+ sanityCheckHeader.setAccessible(true);
+ Method sanityCheckFooter = LegacyGrid.Footer.class
+ .getDeclaredMethod("sanityCheck");
+ sanityCheckFooter.setAccessible(true);
+ sanityCheckHeader.invoke(getHeader());
+ sanityCheckFooter.invoke(getFooter());
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java
new file mode 100644
index 0000000000..1199486742
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2000-2016 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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.SelectionEvent;
+import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.ui.LegacyGrid.MultiSelectionModel;
+import com.vaadin.ui.LegacyGrid.SelectionMode;
+
+public class MultiSelectionModelTest {
+
+ private Object itemId1Present = "itemId1Present";
+ private Object itemId2Present = "itemId2Present";
+ private Object itemId3Present = "itemId3Present";
+
+ private Object itemIdNotPresent = "itemIdNotPresent";
+ private Container.Indexed dataSource;
+ private MultiSelectionModel model;
+ private LegacyGrid grid;
+
+ private boolean expectingEvent = false;
+ private boolean expectingDeselectEvent;
+ private List<Object> select = new ArrayList<Object>();
+ private List<Object> deselect = new ArrayList<Object>();
+
+ @Before
+ public void setUp() {
+ dataSource = createDataSource();
+ grid = new LegacyGrid(dataSource);
+ grid.setSelectionMode(SelectionMode.MULTI);
+ model = (MultiSelectionModel) grid.getSelectionModel();
+ }
+
+ @After
+ public void tearDown() {
+ Assert.assertFalse("Some expected select event did not happen.",
+ expectingEvent);
+ Assert.assertFalse("Some expected deselect event did not happen.",
+ expectingDeselectEvent);
+ }
+
+ private IndexedContainer createDataSource() {
+ final IndexedContainer container = new IndexedContainer();
+ container.addItem(itemId1Present);
+ container.addItem(itemId2Present);
+ container.addItem(itemId3Present);
+ for (int i = 3; i < 10; i++) {
+ container.addItem(new Object());
+ }
+
+ return container;
+ }
+
+ @Test
+ public void testSelectAndDeselectRow() throws Throwable {
+ try {
+ expectSelectEvent(itemId1Present);
+ model.select(itemId1Present);
+ expectDeselectEvent(itemId1Present);
+ model.deselect(itemId1Present);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+
+ verifyCurrentSelection();
+ }
+
+ @Test
+ public void testAddSelection() throws Throwable {
+ try {
+ expectSelectEvent(itemId1Present);
+ model.select(itemId1Present);
+ expectSelectEvent(itemId2Present);
+ model.select(itemId2Present);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+
+ verifyCurrentSelection(itemId1Present, itemId2Present);
+ }
+
+ @Test
+ public void testSettingSelection() throws Throwable {
+ try {
+ expectSelectEvent(itemId2Present, itemId1Present);
+ model.setSelected(Arrays
+ .asList(new Object[] { itemId1Present, itemId2Present }));
+ verifyCurrentSelection(itemId1Present, itemId2Present);
+
+ expectDeselectEvent(itemId1Present);
+ expectSelectEvent(itemId3Present);
+ model.setSelected(Arrays
+ .asList(new Object[] { itemId3Present, itemId2Present }));
+ verifyCurrentSelection(itemId3Present, itemId2Present);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ }
+
+ private void expectSelectEvent(Object... selectArray) {
+ select = Arrays.asList(selectArray);
+ addListener();
+ }
+
+ private void expectDeselectEvent(Object... deselectArray) {
+ deselect = Arrays.asList(deselectArray);
+ addListener();
+ }
+
+ private void addListener() {
+ if (expectingEvent) {
+ return;
+ }
+
+ expectingEvent = true;
+ grid.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void select(SelectionEvent event) {
+ Assert.assertTrue("Selection did not contain expected items",
+ event.getAdded().containsAll(select));
+ Assert.assertTrue("Selection contained unexpected items",
+ select.containsAll(event.getAdded()));
+ select = new ArrayList<Object>();
+
+ Assert.assertTrue("Deselection did not contain expected items",
+ event.getRemoved().containsAll(deselect));
+ Assert.assertTrue("Deselection contained unexpected items",
+ deselect.containsAll(event.getRemoved()));
+ deselect = new ArrayList<Object>();
+
+ grid.removeSelectionListener(this);
+ expectingEvent = false;
+ }
+ });
+ }
+
+ private void verifyCurrentSelection(Object... selection) {
+ final List<Object> selected = Arrays.asList(selection);
+ if (model.getSelectedRows().containsAll(selected)
+ && selected.containsAll(model.getSelectedRows())) {
+ return;
+ }
+ Assert.fail("Not all items were correctly selected");
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java
new file mode 100644
index 0000000000..3183ad9021
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2000-2016 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.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.SelectionEvent;
+import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.ui.LegacyGrid;
+import com.vaadin.ui.LegacyGrid.SelectionMode;
+import com.vaadin.ui.LegacyGrid.SingleSelectionModel;
+
+public class SingleSelectionModelTest {
+
+ private Object itemId1Present = "itemId1Present";
+ private Object itemId2Present = "itemId2Present";
+
+ private Object itemIdNotPresent = "itemIdNotPresent";
+ private Container.Indexed dataSource;
+ private SingleSelectionModel model;
+ private LegacyGrid grid;
+
+ private boolean expectingEvent = false;
+
+ @Before
+ public void setUp() {
+ dataSource = createDataSource();
+ grid = new LegacyGrid(dataSource);
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ model = (SingleSelectionModel) grid.getSelectionModel();
+ }
+
+ @After
+ public void tearDown() {
+ Assert.assertFalse("Some expected event did not happen.",
+ expectingEvent);
+ }
+
+ private IndexedContainer createDataSource() {
+ final IndexedContainer container = new IndexedContainer();
+ container.addItem(itemId1Present);
+ container.addItem(itemId2Present);
+ for (int i = 2; i < 10; i++) {
+ container.addItem(new Object());
+ }
+
+ return container;
+ }
+
+ @Test
+ public void testSelectAndDeselctRow() throws Throwable {
+ try {
+ expectEvent(itemId1Present, null);
+ model.select(itemId1Present);
+ expectEvent(null, itemId1Present);
+ model.select(null);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ }
+
+ @Test
+ public void testSelectAndChangeSelectedRow() throws Throwable {
+ try {
+ expectEvent(itemId1Present, null);
+ model.select(itemId1Present);
+ expectEvent(itemId2Present, itemId1Present);
+ model.select(itemId2Present);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ }
+
+ @Test
+ public void testRemovingSelectedRowAndThenDeselecting() throws Throwable {
+ try {
+ expectEvent(itemId2Present, null);
+ model.select(itemId2Present);
+ dataSource.removeItem(itemId2Present);
+ expectEvent(null, itemId2Present);
+ model.select(null);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ }
+
+ @Test
+ public void testSelectAndReSelectRow() throws Throwable {
+ try {
+ expectEvent(itemId1Present, null);
+ model.select(itemId1Present);
+ expectEvent(null, null);
+ // This is no-op. Nothing should happen.
+ model.select(itemId1Present);
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ Assert.assertTrue("Should still wait for event", expectingEvent);
+ expectingEvent = false;
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSelectNonExistentRow() {
+ model.select(itemIdNotPresent);
+ }
+
+ private void expectEvent(final Object selected, final Object deselected) {
+ expectingEvent = true;
+ grid.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void select(SelectionEvent event) {
+ if (selected != null) {
+ Assert.assertTrue("Selection did not contain expected item",
+ event.getAdded().contains(selected));
+ } else {
+ Assert.assertTrue("Unexpected selection",
+ event.getAdded().isEmpty());
+ }
+
+ if (deselected != null) {
+ Assert.assertTrue(
+ "DeSelection did not contain expected item",
+ event.getRemoved().contains(deselected));
+ } else {
+ Assert.assertTrue("Unexpected selection",
+ event.getRemoved().isEmpty());
+ }
+
+ grid.removeSelectionListener(this);
+ expectingEvent = false;
+ }
+ });
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java
new file mode 100644
index 0000000000..9b2dde4d24
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2016 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 java.lang.reflect.Field;
+
+import org.easymock.EasyMock;
+
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.communication.data.RpcDataProviderExtension;
+import com.vaadin.ui.ConnectorTracker;
+import com.vaadin.ui.LegacyGrid;
+import com.vaadin.ui.UI;
+
+/**
+ * A Grid attached to a mock UI with a mock ConnectorTracker.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class TestGrid extends LegacyGrid {
+
+ public TestGrid() {
+ super();
+ init();
+ }
+
+ public TestGrid(IndexedContainer c) {
+ super(c);
+ init();
+ }
+
+ public RpcDataProviderExtension getDataProvider() throws Exception {
+ Field dseField = LegacyGrid.class.getDeclaredField("datasourceExtension");
+ dseField.setAccessible(true);
+ return (RpcDataProviderExtension) dseField.get(this);
+ }
+
+ private void init() {
+ UI mockUI = EasyMock.createNiceMock(UI.class);
+ ConnectorTracker mockCT = EasyMock
+ .createNiceMock(ConnectorTracker.class);
+ EasyMock.expect(mockUI.getConnectorTracker()).andReturn(mockCT)
+ .anyTimes();
+ EasyMock.replay(mockUI, mockCT);
+
+ setParent(mockUI);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java
new file mode 100644
index 0000000000..71d24a2d8e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2016 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.declarative;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Test;
+
+public class GridColumnDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testSimpleGridColumns() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable width='100' property-id='Column1'>"
+ + " <col sortable=false max-width='200' expand='2' property-id='Column2'>"
+ + " <col sortable editable=false resizable=false min-width='15' expand='1' property-id='Column3'>"
+ + " <col sortable hidable hiding-toggle-caption='col 4' property-id='Column4'>"
+ + " <col sortable hidden property-id='Column5'>"
+ + "</colgroup>" //
+ + "<thead />" //
+ + "</table></vaadin-legacy-grid>";
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class).setWidth(100);
+ grid.addColumn("Column2", String.class).setMaximumWidth(200)
+ .setExpandRatio(2).setSortable(false);
+ grid.addColumn("Column3", String.class).setMinimumWidth(15)
+ .setExpandRatio(1).setEditable(false).setResizable(false);
+ grid.addColumn("Column4", String.class).setHidable(true)
+ .setHidingToggleCaption("col 4").setResizable(true);
+ grid.addColumn("Column5", String.class).setHidden(true);
+
+ // Remove the default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ // Use the read grid component to do another pass on write.
+ testRead(design, grid, true);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testReadColumnsWithoutPropertyId() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true width='100' property-id='Column1'>"
+ + " <col sortable=true max-width='200' expand='2'>" // property-id="property-1"
+ + " <col sortable=true min-width='15' expand='1' property-id='Column3'>"
+ + " <col sortable=true hidden=true hidable=true hiding-toggle-caption='col 4'>" // property-id="property-3"
+ + "</colgroup>" //
+ + "</table></vaadin-legacy-grid>";
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class).setWidth(100);
+ grid.addColumn("property-1", String.class).setMaximumWidth(200)
+ .setExpandRatio(2);
+ grid.addColumn("Column3", String.class).setMinimumWidth(15)
+ .setExpandRatio(1);
+ grid.addColumn("property-3", String.class).setHidable(true)
+ .setHidden(true).setHidingToggleCaption("col 4");
+
+ testRead(design, grid);
+ }
+
+ @Test
+ public void testReadEmptyExpand() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>" + " <col sortable=true expand />"
+ + "</colgroup>" //
+ + "</table></vaadin-legacy-grid>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("property-0", String.class).setExpandRatio(1);
+
+ testRead(design, grid);
+ }
+
+ @Test
+ public void testReadColumnWithNoAttributes() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>" //
+ + " <col />" //
+ + "</colgroup>" //
+ + "</table></vaadin-legacy-grid>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("property-0", String.class);
+
+ testRead(design, grid);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java
new file mode 100644
index 0000000000..8ca99327dc
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2016 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.declarative;
+
+import static org.junit.Assert.assertSame;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Test;
+
+import com.vaadin.shared.ui.grid.HeightMode;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.LegacyGrid.MultiSelectionModel;
+import com.vaadin.ui.LegacyGrid.NoSelectionModel;
+import com.vaadin.ui.LegacyGrid.SingleSelectionModel;
+
+/**
+ * Tests declarative support for {@link Grid} properties.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridDeclarativeAttributeTest extends DeclarativeTestBase<LegacyGrid> {
+
+ @Test
+ public void testBasicAttributes() {
+
+ String design = "<vaadin-legacy-grid editable rows=20 frozen-columns=-1 "
+ + "editor-save-caption='Tallenna' editor-cancel-caption='Peruuta' column-reordering-allowed>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.setEditorEnabled(true);
+ grid.setHeightMode(HeightMode.ROW);
+ grid.setHeightByRows(20);
+ grid.setFrozenColumnCount(-1);
+ grid.setEditorSaveCaption("Tallenna");
+ grid.setEditorCancelCaption("Peruuta");
+ grid.setColumnReorderingAllowed(true);
+
+ testRead(design, grid);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testFrozenColumnsAttributes() {
+ String design = "<vaadin-legacy-grid frozen-columns='2'><table>" //
+ + "<colgroup><col><col><col></colgroup></table></vaadin-legacy-grid>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("property-0", String.class);
+ grid.addColumn("property-1", String.class);
+ grid.addColumn("property-2", String.class);
+ grid.setFrozenColumnCount(2);
+
+ testRead(design, grid);
+ }
+
+ @Test
+ public void testSelectionMode() {
+ String design = "<vaadin-legacy-grid selection-mode='none'>";
+ assertSame(NoSelectionModel.class,
+ read(design).getSelectionModel().getClass());
+
+ design = "<vaadin-legacy-grid selection-mode='single'>";
+ assertSame(SingleSelectionModel.class,
+ read(design).getSelectionModel().getClass());
+
+ design = "<vaadin-legacy-grid selection-mode='multi'>";
+ assertSame(MultiSelectionModel.class,
+ read(design).getSelectionModel().getClass());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java
new file mode 100644
index 0000000000..3e97910be7
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000-2016 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.declarative;
+
+import java.util.List;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Assert;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.LegacyGrid.Column;
+import com.vaadin.ui.LegacyGrid.FooterCell;
+import com.vaadin.ui.LegacyGrid.FooterRow;
+import com.vaadin.ui.LegacyGrid.HeaderCell;
+import com.vaadin.ui.LegacyGrid.HeaderRow;
+
+public class GridDeclarativeTestBase extends DeclarativeTestBase<LegacyGrid> {
+
+ @Override
+ public LegacyGrid testRead(String design, LegacyGrid expected) {
+ return testRead(design, expected, false);
+ }
+
+ public LegacyGrid testRead(String design, LegacyGrid expected, boolean retestWrite) {
+ return testRead(design, expected, retestWrite, false);
+ }
+
+ public LegacyGrid testRead(String design, LegacyGrid expected, boolean retestWrite,
+ boolean writeData) {
+ LegacyGrid actual = super.testRead(design, expected);
+
+ compareGridColumns(expected, actual);
+ compareHeaders(expected, actual);
+ compareFooters(expected, actual);
+
+ if (retestWrite) {
+ testWrite(design, actual, writeData);
+ }
+
+ return actual;
+ }
+
+ private void compareHeaders(LegacyGrid expected, LegacyGrid actual) {
+ Assert.assertEquals("Different header row count",
+ expected.getHeaderRowCount(), actual.getHeaderRowCount());
+ for (int i = 0; i < expected.getHeaderRowCount(); ++i) {
+ HeaderRow expectedRow = expected.getHeaderRow(i);
+ HeaderRow actualRow = actual.getHeaderRow(i);
+
+ if (expectedRow.equals(expected.getDefaultHeaderRow())) {
+ Assert.assertEquals("Different index for default header row",
+ actual.getDefaultHeaderRow(), actualRow);
+ }
+
+ for (Column c : expected.getColumns()) {
+ String baseError = "Difference when comparing cell for "
+ + c.toString() + " on header row " + i + ": ";
+ Object propertyId = c.getPropertyId();
+ HeaderCell expectedCell = expectedRow.getCell(propertyId);
+ HeaderCell actualCell = actualRow.getCell(propertyId);
+
+ switch (expectedCell.getCellType()) {
+ case TEXT:
+ Assert.assertEquals(baseError + "Text content",
+ expectedCell.getText(), actualCell.getText());
+ break;
+ case HTML:
+ Assert.assertEquals(baseError + "HTML content",
+ expectedCell.getHtml(), actualCell.getHtml());
+ break;
+ case WIDGET:
+ assertEquals(baseError + "Component content",
+ expectedCell.getComponent(),
+ actualCell.getComponent());
+ break;
+ }
+ }
+ }
+ }
+
+ private void compareFooters(LegacyGrid expected, LegacyGrid actual) {
+ Assert.assertEquals("Different footer row count",
+ expected.getFooterRowCount(), actual.getFooterRowCount());
+ for (int i = 0; i < expected.getFooterRowCount(); ++i) {
+ FooterRow expectedRow = expected.getFooterRow(i);
+ FooterRow actualRow = actual.getFooterRow(i);
+
+ for (Column c : expected.getColumns()) {
+ String baseError = "Difference when comparing cell for "
+ + c.toString() + " on footer row " + i + ": ";
+ Object propertyId = c.getPropertyId();
+ FooterCell expectedCell = expectedRow.getCell(propertyId);
+ FooterCell actualCell = actualRow.getCell(propertyId);
+
+ switch (expectedCell.getCellType()) {
+ case TEXT:
+ Assert.assertEquals(baseError + "Text content",
+ expectedCell.getText(), actualCell.getText());
+ break;
+ case HTML:
+ Assert.assertEquals(baseError + "HTML content",
+ expectedCell.getHtml(), actualCell.getHtml());
+ break;
+ case WIDGET:
+ assertEquals(baseError + "Component content",
+ expectedCell.getComponent(),
+ actualCell.getComponent());
+ break;
+ }
+ }
+ }
+ }
+
+ private void compareGridColumns(LegacyGrid expected, LegacyGrid actual) {
+ List<Column> columns = expected.getColumns();
+ List<Column> actualColumns = actual.getColumns();
+ Assert.assertEquals("Different amount of columns", columns.size(),
+ actualColumns.size());
+ for (int i = 0; i < columns.size(); ++i) {
+ Column col1 = columns.get(i);
+ Column col2 = actualColumns.get(i);
+ String baseError = "Error when comparing columns for property "
+ + col1.getPropertyId() + ": ";
+ assertEquals(baseError + "Property id", col1.getPropertyId(),
+ col2.getPropertyId());
+ assertEquals(baseError + "Width", col1.getWidth(), col2.getWidth());
+ assertEquals(baseError + "Maximum width", col1.getMaximumWidth(),
+ col2.getMaximumWidth());
+ assertEquals(baseError + "Minimum width", col1.getMinimumWidth(),
+ col2.getMinimumWidth());
+ assertEquals(baseError + "Expand ratio", col1.getExpandRatio(),
+ col2.getExpandRatio());
+ assertEquals(baseError + "Sortable", col1.isSortable(),
+ col2.isSortable());
+ assertEquals(baseError + "Editable", col1.isEditable(),
+ col2.isEditable());
+ assertEquals(baseError + "Hidable", col1.isHidable(),
+ col2.isHidable());
+ assertEquals(baseError + "Hidden", col1.isHidden(),
+ col2.isHidden());
+ assertEquals(baseError + "HidingToggleCaption",
+ col1.getHidingToggleCaption(),
+ col2.getHidingToggleCaption());
+ }
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java
new file mode 100644
index 0000000000..1207063c16
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2000-2016 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.declarative;
+
+import com.vaadin.ui.LegacyGrid;
+import org.jsoup.nodes.Element;
+import org.jsoup.parser.Tag;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.LegacyGrid.Column;
+import com.vaadin.ui.LegacyGrid.FooterRow;
+import com.vaadin.ui.LegacyGrid.HeaderRow;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.declarative.DesignContext;
+
+public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testSingleDefaultHeader() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + " <col sortable property-id='Column2'>"
+ + " <col sortable property-id='Column3'>"
+ + "</colgroup>"
+ + "<thead>"
+ + " <tr default><th plain-text>Column1<th plain-text>Column2<th plain-text>Column3</tr>"
+ + "</thead>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testSingleDefaultHTMLHeader() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + " <col sortable property-id='Column2'>"
+ + " <col sortable property-id='Column3'>" + "</colgroup>"
+ + "<thead>"
+ + " <tr default><th>Column1<th>Column2<th>Column3</tr>"
+ + "</thead>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ HeaderRow row = grid.getDefaultHeaderRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testNoHeaderRows() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + "</colgroup>"
+ + "<thead />"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testMultipleHeadersWithColSpans() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + " <col sortable property-id='Column2'>"
+ + " <col sortable property-id='Column3'>"
+ + "</colgroup>"
+ + "<thead>"
+ + " <tr><th colspan=3>Baz</tr>"
+ + " <tr default><th>Column1<th>Column2<th>Column3</tr>"
+ + " <tr><th>Foo<th colspan=2>Bar</tr>"
+ + "</thead>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ HeaderRow row = grid.getDefaultHeaderRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ grid.prependHeaderRow().join("Column1", "Column2", "Column3")
+ .setHtml("Baz");
+ row = grid.appendHeaderRow();
+ row.getCell("Column1").setHtml("Foo");
+ row.join("Column2", "Column3").setHtml("Bar");
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testSingleDefaultFooter() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + " <col sortable property-id='Column2'>"
+ + " <col sortable property-id='Column3'>"
+ + "</colgroup>"
+ + "<thead />" // No headers read or written
+ + "<tfoot>"
+ + " <tr><td plain-text>Column1<td plain-text>Column2<td plain-text>Column3</tr>"
+ + "</tfoot>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ FooterRow row = grid.appendFooterRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setText(c.getHeaderCaption());
+ }
+
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testSingleDefaultHTMLFooter() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + " <col sortable property-id='Column2'>"
+ + " <col sortable property-id='Column3'>" + "</colgroup>"
+ + "<thead />" // No headers read or written
+ + "<tfoot>"
+ + " <tr><td>Column1<td>Column2<td>Column3</tr>"
+ + "</tfoot>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ FooterRow row = grid.appendFooterRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testMultipleFootersWithColSpans() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + " <col sortable property-id='Column2'>"
+ + " <col sortable property-id='Column3'>"
+ + "</colgroup>"
+ + "<thead />" // No headers read or written.
+ + "<tfoot>"
+ + " <tr><td colspan=3>Baz</tr>"
+ + " <tr><td>Column1<td>Column2<td>Column3</tr>"
+ + " <tr><td>Foo<td colspan=2>Bar</tr>"
+ + "</tfoot>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ FooterRow row = grid.appendFooterRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ grid.prependFooterRow().join("Column1", "Column2", "Column3")
+ .setHtml("Baz");
+ row = grid.appendFooterRow();
+ row.getCell("Column1").setHtml("Foo");
+ row.join("Column2", "Column3").setHtml("Bar");
+
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testComponentInGridHeader() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + "</colgroup>"
+ + "<thead>"
+ + "<tr default><th><vaadin-label><b>Foo</b></vaadin-label></tr>"
+ + "</thead>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+ Label component = new Label("<b>Foo</b>");
+ component.setContentMode(ContentMode.HTML);
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.getDefaultHeaderRow().getCell("Column1").setComponent(component);
+
+ testRead(design, grid, true);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testComponentInGridFooter() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable property-id='Column1'>"
+ + "</colgroup>"
+ + "<thead />" // No headers read or written
+ + "<tfoot>"
+ + "<tr><td><vaadin-label><b>Foo</b></vaadin-label></tr>"
+ + "</tfoot>"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+
+ Label component = new Label("<b>Foo</b>");
+ component.setContentMode(ContentMode.HTML);
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Column1", String.class);
+ grid.prependFooterRow().getCell("Column1").setComponent(component);
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testRead(design, grid, true);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testHtmlEntitiesinGridHeaderFooter() {
+ //@formatter:off
+ String design = "<vaadin-legacy-grid><table>"
+ + "<colgroup>"
+ + " <col sortable=\"true\" property-id=\"> test\">"
+ + "</colgroup>"
+ + "<thead>"
+ + " <tr><th plain-text=\"true\">&gt; Test</th></tr>"
+ + "</thead>"
+ + "<tfoot>"
+ + " <tr><td plain-text=\"true\">&gt; Test</td></tr>"
+ + "</tfoot>"
+ + "<tbody />"
+ + "</table></vaadin-legacy-grid>";
+ //@formatter:on
+
+ LegacyGrid grid = read(design);
+ String actualHeader = grid.getHeaderRow(0).getCell("> test").getText();
+ String actualFooter = grid.getFooterRow(0).getCell("> test").getText();
+ String expected = "> Test";
+
+ Assert.assertEquals(expected, actualHeader);
+ Assert.assertEquals(expected, actualFooter);
+
+ design = design.replace("plain-text=\"true\"", "");
+ grid = read(design);
+ actualHeader = grid.getHeaderRow(0).getCell("> test").getHtml();
+ actualFooter = grid.getFooterRow(0).getCell("> test").getHtml();
+ expected = "&gt; Test";
+
+ Assert.assertEquals(expected, actualHeader);
+ Assert.assertEquals(expected, actualFooter);
+
+ grid = new LegacyGrid();
+ grid.setColumns("test");
+ HeaderRow header = grid.addHeaderRowAt(0);
+ FooterRow footer = grid.addFooterRowAt(0);
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ // entities should be encoded when writing back, not interpreted as HTML
+ header.getCell("test").setText("&amp; Test");
+ footer.getCell("test").setText("&amp; Test");
+
+ Element root = new Element(Tag.valueOf("vaadin-legacy-grid"), "");
+ grid.writeDesign(root, new DesignContext());
+
+ Assert.assertEquals("&amp;amp; Test",
+ root.getElementsByTag("th").get(0).html());
+ Assert.assertEquals("&amp;amp; Test",
+ root.getElementsByTag("td").get(0).html());
+
+ header = grid.addHeaderRowAt(0);
+ footer = grid.addFooterRowAt(0);
+
+ // entities should not be encoded, this is already given as HTML
+ header.getCell("test").setHtml("&amp; Test");
+ footer.getCell("test").setHtml("&amp; Test");
+
+ root = new Element(Tag.valueOf("vaadin-legacy-grid"), "");
+ grid.writeDesign(root, new DesignContext());
+
+ Assert.assertEquals("&amp; Test",
+ root.getElementsByTag("th").get(0).html());
+ Assert.assertEquals("&amp; Test",
+ root.getElementsByTag("td").get(0).html());
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java
new file mode 100644
index 0000000000..f5b98824cd
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2016 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.declarative;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+
+public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testSimpleInlineData() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>" + " <col sortable property-id='Col1' />"
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + "<tr><td>Foo</tr>" //
+ + "<tr><td>Bar</tr>" //
+ + "<tr><td>Baz</tr>" //
+ + "</tbody>" //
+ + "</table></vaadin-legacy-grid>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Col1", String.class);
+ grid.addRow("Foo");
+ grid.addRow("Bar");
+ grid.addRow("Baz");
+
+ // Remove default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid, true);
+ testRead(design, grid, true, true);
+ }
+
+ @Test
+ public void testMultipleColumnsInlineData() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>" + " <col sortable property-id='Col1' />"
+ + " <col sortable property-id='Col2' />"
+ + " <col sortable property-id='Col3' />" //
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + "<tr><td>Foo<td>Bar<td>Baz</tr>" //
+ + "<tr><td>My<td>Summer<td>Car</tr>" //
+ + "</tbody>" //
+ + "</table></vaadin-legacy-grid>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Col1", String.class);
+ grid.addColumn("Col2", String.class);
+ grid.addColumn("Col3", String.class);
+ grid.addRow("Foo", "Bar", "Baz");
+ grid.addRow("My", "Summer", "Car");
+
+ // Remove default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid, true);
+ testRead(design, grid, true, true);
+ }
+
+ @Test
+ public void testMultipleColumnsInlineDataReordered() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>" + " <col sortable property-id='Col2' />"
+ + " <col sortable property-id='Col3' />"
+ + " <col sortable property-id='Col1' />" //
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + "<tr><td>Bar<td>Baz<td>Foo</tr>" //
+ + "<tr><td>Summer<td>Car<td>My</tr>" //
+ + "</tbody>" //
+ + "</table></vaadin-legacy-grid>";
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.addColumn("Col1", String.class);
+ grid.addColumn("Col2", String.class);
+ grid.addColumn("Col3", String.class);
+ grid.addRow("Foo", "Bar", "Baz");
+ grid.addRow("My", "Summer", "Car");
+ grid.setColumnOrder("Col2", "Col3", "Col1");
+
+ // Remove default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid, true);
+ testRead(design, grid, true, true);
+ }
+
+ @Test
+ public void testHtmlEntities() {
+ String design = "<vaadin-legacy-grid><table>"//
+ + "<colgroup>" + " <col property-id='test' />" + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + " <tr><td>&amp;Test</tr></td>" + "</tbody>"
+ + "</table></vaadin-legacy-grid>";
+
+ LegacyGrid read = read(design);
+ Container cds = read.getContainerDataSource();
+ Assert.assertEquals("&amp;Test",
+ cds.getItem(cds.getItemIds().iterator().next())
+ .getItemProperty("test").getValue());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java
new file mode 100644
index 0000000000..b55b0815f8
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2016 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.declarative;
+
+import com.vaadin.ui.LegacyGrid;
+import org.junit.Test;
+
+import com.vaadin.ui.declarative.DesignException;
+
+public class GridStructureDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testReadEmptyGrid() {
+ String design = "<vaadin-legacy-grid />";
+ testRead(design, new LegacyGrid(), false);
+ }
+
+ @Test
+ public void testEmptyGrid() {
+ String design = "<vaadin-legacy-grid></vaadin-legacy-grid>";
+ LegacyGrid expected = new LegacyGrid();
+ testWrite(design, expected);
+ testRead(design, expected, true);
+ }
+
+ @Test(expected = DesignException.class)
+ public void testMalformedGrid() {
+ String design = "<vaadin-legacy-grid><vaadin-label /></vaadin-legacy-grid>";
+ testRead(design, new LegacyGrid());
+ }
+
+ @Test(expected = DesignException.class)
+ public void testGridWithNoColGroup() {
+ String design = "<vaadin-legacy-grid><table><thead><tr><th>Foo</tr></thead></table></vaadin-legacy-grid>";
+ testRead(design, new LegacyGrid());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java
new file mode 100644
index 0000000000..beb774528f
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2000-2016 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.sort;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.sort.Sort;
+import com.vaadin.data.sort.SortOrder;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.SortEvent;
+import com.vaadin.event.SortEvent.SortListener;
+import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.ui.LegacyGrid;
+
+public class SortTest {
+
+ class DummySortingIndexedContainer extends IndexedContainer {
+
+ private Object[] expectedProperties;
+ private boolean[] expectedAscending;
+ private boolean sorted = true;
+
+ @Override
+ public void sort(Object[] propertyId, boolean[] ascending) {
+ Assert.assertEquals(
+ "Different amount of expected and actual properties,",
+ expectedProperties.length, propertyId.length);
+ Assert.assertEquals(
+ "Different amount of expected and actual directions",
+ expectedAscending.length, ascending.length);
+ for (int i = 0; i < propertyId.length; ++i) {
+ Assert.assertEquals("Sorting properties differ",
+ expectedProperties[i], propertyId[i]);
+ Assert.assertEquals("Sorting directions differ",
+ expectedAscending[i], ascending[i]);
+ }
+ sorted = true;
+ }
+
+ public void expectedSort(Object[] properties,
+ SortDirection[] directions) {
+ assert directions.length == properties.length : "Array dimensions differ";
+ expectedProperties = properties;
+ expectedAscending = new boolean[directions.length];
+ for (int i = 0; i < directions.length; ++i) {
+ expectedAscending[i] = (directions[i] == SortDirection.ASCENDING);
+ }
+ sorted = false;
+ }
+
+ public boolean isSorted() {
+ return sorted;
+ }
+ }
+
+ class RegisteringSortChangeListener implements SortListener {
+ private List<SortOrder> order;
+
+ @Override
+ public void sort(SortEvent event) {
+ assert order == null : "The same listener was notified multipe times without checking";
+
+ order = event.getSortOrder();
+ }
+
+ public void assertEventFired(SortOrder... expectedOrder) {
+ Assert.assertEquals(Arrays.asList(expectedOrder), order);
+
+ // Reset for nest test
+ order = null;
+ }
+
+ }
+
+ private DummySortingIndexedContainer container;
+ private RegisteringSortChangeListener listener;
+ private LegacyGrid grid;
+
+ @Before
+ public void setUp() {
+ container = createContainer();
+ container.expectedSort(new Object[] {}, new SortDirection[] {});
+
+ listener = new RegisteringSortChangeListener();
+
+ grid = new LegacyGrid(container);
+ grid.addSortListener(listener);
+ }
+
+ @After
+ public void tearDown() {
+ Assert.assertTrue("Container was not sorted after the test.",
+ container.isSorted());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidSortDirection() {
+ Sort.by("foo", null);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testSortOneColumnMultipleTimes() {
+ Sort.by("foo").then("bar").then("foo");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSortingByUnexistingProperty() {
+ grid.sort("foobar");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSortingByUnsortableProperty() {
+ container.addContainerProperty("foobar", Object.class, null);
+ grid.sort("foobar");
+ }
+
+ @Test
+ public void testGridDirectSortAscending() {
+ container.expectedSort(new Object[] { "foo" },
+ new SortDirection[] { SortDirection.ASCENDING });
+ grid.sort("foo");
+
+ listener.assertEventFired(
+ new SortOrder("foo", SortDirection.ASCENDING));
+ }
+
+ @Test
+ public void testGridDirectSortDescending() {
+ container.expectedSort(new Object[] { "foo" },
+ new SortDirection[] { SortDirection.DESCENDING });
+ grid.sort("foo", SortDirection.DESCENDING);
+
+ listener.assertEventFired(
+ new SortOrder("foo", SortDirection.DESCENDING));
+ }
+
+ @Test
+ public void testGridSortBy() {
+ container.expectedSort(new Object[] { "foo", "bar", "baz" },
+ new SortDirection[] { SortDirection.ASCENDING,
+ SortDirection.ASCENDING, SortDirection.DESCENDING });
+ grid.sort(Sort.by("foo").then("bar").then("baz",
+ SortDirection.DESCENDING));
+
+ listener.assertEventFired(new SortOrder("foo", SortDirection.ASCENDING),
+ new SortOrder("bar", SortDirection.ASCENDING),
+ new SortOrder("baz", SortDirection.DESCENDING));
+
+ }
+
+ @Test
+ public void testChangeContainerAfterSorting() {
+ class Person {
+ }
+
+ container.expectedSort(new Object[] { "foo", "bar", "baz" },
+ new SortDirection[] { SortDirection.ASCENDING,
+ SortDirection.ASCENDING, SortDirection.DESCENDING });
+ grid.sort(Sort.by("foo").then("bar").then("baz",
+ SortDirection.DESCENDING));
+
+ listener.assertEventFired(new SortOrder("foo", SortDirection.ASCENDING),
+ new SortOrder("bar", SortDirection.ASCENDING),
+ new SortOrder("baz", SortDirection.DESCENDING));
+
+ container = new DummySortingIndexedContainer();
+ container.addContainerProperty("foo", Person.class, null);
+ container.addContainerProperty("baz", String.class, "");
+ container.addContainerProperty("bar", Person.class, null);
+ container.expectedSort(new Object[] { "baz" },
+ new SortDirection[] { SortDirection.DESCENDING });
+ grid.setContainerDataSource(container);
+
+ listener.assertEventFired(
+ new SortOrder("baz", SortDirection.DESCENDING));
+
+ }
+
+ private DummySortingIndexedContainer createContainer() {
+ DummySortingIndexedContainer container = new DummySortingIndexedContainer();
+ container.addContainerProperty("foo", Integer.class, 0);
+ container.addContainerProperty("bar", Integer.class, 0);
+ container.addContainerProperty("baz", Integer.class, 0);
+ return container;
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java
new file mode 100644
index 0000000000..822a2353ac
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2016 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.renderer;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.ClassResource;
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.FileResource;
+import com.vaadin.server.FontAwesome;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.ui.LegacyGrid;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.renderers.ImageRenderer;
+
+import elemental.json.JsonObject;
+import elemental.json.JsonValue;
+
+public class ImageRendererTest {
+
+ private ImageRenderer renderer;
+
+ @Before
+ public void setUp() {
+ UI mockUI = EasyMock.createNiceMock(UI.class);
+ EasyMock.replay(mockUI);
+
+ LegacyGrid grid = new LegacyGrid();
+ grid.setParent(mockUI);
+
+ renderer = new ImageRenderer();
+ renderer.setParent(grid);
+ }
+
+ @Test
+ public void testThemeResource() {
+ JsonValue v = renderer.encode(new ThemeResource("foo.png"));
+ assertEquals("theme://foo.png", getUrl(v));
+ }
+
+ @Test
+ public void testExternalResource() {
+ JsonValue v = renderer
+ .encode(new ExternalResource("http://example.com/foo.png"));
+ assertEquals("http://example.com/foo.png", getUrl(v));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFileResource() {
+ renderer.encode(new FileResource(new File("/tmp/foo.png")));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testClassResource() {
+ renderer.encode(new ClassResource("img/foo.png"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFontIcon() {
+ renderer.encode(FontAwesome.AMBULANCE);
+ }
+
+ private String getUrl(JsonValue v) {
+ return ((JsonObject) v).get("uRL").asString();
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java
new file mode 100644
index 0000000000..5eec5b6ea8
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2000-2016 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.renderer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.server.component.grid.TestGrid;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.ui.LegacyGrid;
+import com.vaadin.ui.LegacyGrid.AbstractRenderer;
+import com.vaadin.ui.LegacyGrid.Column;
+import com.vaadin.ui.renderers.ButtonRenderer;
+import com.vaadin.ui.renderers.DateRenderer;
+import com.vaadin.ui.renderers.HtmlRenderer;
+import com.vaadin.ui.renderers.NumberRenderer;
+import com.vaadin.ui.renderers.TextRenderer;
+import com.vaadin.v7.data.util.converter.LegacyConverter;
+import com.vaadin.v7.data.util.converter.LegacyStringToIntegerConverter;
+
+import elemental.json.JsonValue;
+
+public class RendererTest {
+
+ private static class TestBean {
+ int i = 42;
+
+ @Override
+ public String toString() {
+ return "TestBean [" + i + "]";
+ }
+ }
+
+ private static class ExtendedBean extends TestBean {
+ float f = 3.14f;
+ }
+
+ private static class TestRenderer extends TextRenderer {
+ @Override
+ public JsonValue encode(String value) {
+ return super.encode("renderer(" + value + ")");
+ }
+ }
+
+ private static class TestConverter
+ implements LegacyConverter<String, TestBean> {
+
+ @Override
+ public TestBean convertToModel(String value,
+ Class<? extends TestBean> targetType, Locale locale)
+ throws ConversionException {
+ return null;
+ }
+
+ @Override
+ public String convertToPresentation(TestBean value,
+ Class<? extends String> targetType, Locale locale)
+ throws ConversionException {
+ if (value instanceof ExtendedBean) {
+ return "ExtendedBean(" + value.i + ", "
+ + ((ExtendedBean) value).f + ")";
+ } else {
+ return "TestBean(" + value.i + ")";
+ }
+ }
+
+ @Override
+ public Class<TestBean> getModelType() {
+ return TestBean.class;
+ }
+
+ @Override
+ public Class<String> getPresentationType() {
+ return String.class;
+ }
+ }
+
+ private LegacyGrid grid;
+
+ private Column intColumn;
+ private Column textColumn;
+ private Column beanColumn;
+ private Column htmlColumn;
+ private Column numberColumn;
+ private Column dateColumn;
+ private Column extendedBeanColumn;
+ private Column buttonColumn;
+
+ @Before
+ @SuppressWarnings("unchecked")
+ public void setUp() {
+ VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null));
+
+ IndexedContainer c = new IndexedContainer();
+
+ c.addContainerProperty("int", Integer.class, 0);
+ c.addContainerProperty("text", String.class, "");
+ c.addContainerProperty("html", String.class, "");
+ c.addContainerProperty("number", Number.class, null);
+ c.addContainerProperty("date", Date.class, null);
+ c.addContainerProperty("bean", TestBean.class, null);
+ c.addContainerProperty("button", String.class, null);
+ c.addContainerProperty("extendedBean", ExtendedBean.class, null);
+
+ Object id = c.addItem();
+ Item item = c.getItem(id);
+ item.getItemProperty("int").setValue(123);
+ item.getItemProperty("text").setValue("321");
+ item.getItemProperty("html").setValue("<b>html</b>");
+ item.getItemProperty("number").setValue(3.14);
+ item.getItemProperty("date").setValue(new Date(123456789));
+ item.getItemProperty("bean").setValue(new TestBean());
+ item.getItemProperty("extendedBean").setValue(new ExtendedBean());
+
+ grid = new TestGrid(c);
+
+ intColumn = grid.getColumn("int");
+ textColumn = grid.getColumn("text");
+ htmlColumn = grid.getColumn("html");
+ numberColumn = grid.getColumn("number");
+ dateColumn = grid.getColumn("date");
+ beanColumn = grid.getColumn("bean");
+ extendedBeanColumn = grid.getColumn("extendedBean");
+ buttonColumn = grid.getColumn("button");
+
+ }
+
+ @Test
+ public void testDefaultRendererAndConverter() throws Exception {
+ assertSame(TextRenderer.class, intColumn.getRenderer().getClass());
+ assertSame(LegacyStringToIntegerConverter.class,
+ intColumn.getConverter().getClass());
+
+ assertSame(TextRenderer.class, textColumn.getRenderer().getClass());
+ // String->String; converter not needed
+ assertNull(textColumn.getConverter());
+
+ assertSame(TextRenderer.class, beanColumn.getRenderer().getClass());
+ // MyBean->String; converter not found
+ assertNull(beanColumn.getConverter());
+ }
+
+ @Test
+ public void testFindCompatibleConverter() throws Exception {
+ intColumn.setRenderer(renderer());
+ assertSame(LegacyStringToIntegerConverter.class,
+ intColumn.getConverter().getClass());
+
+ textColumn.setRenderer(renderer());
+ assertNull(textColumn.getConverter());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCannotFindConverter() {
+ beanColumn.setRenderer(renderer());
+ }
+
+ @Test
+ public void testExplicitConverter() throws Exception {
+ beanColumn.setRenderer(renderer(), converter());
+ extendedBeanColumn.setRenderer(renderer(), converter());
+ }
+
+ @Test
+ public void testEncoding() throws Exception {
+ assertEquals("42", render(intColumn, 42).asString());
+ intColumn.setRenderer(renderer());
+ assertEquals("renderer(42)", render(intColumn, 42).asString());
+
+ assertEquals("2.72", render(textColumn, "2.72").asString());
+ textColumn.setRenderer(new TestRenderer());
+ assertEquals("renderer(2.72)", render(textColumn, "2.72").asString());
+ }
+
+ @Test
+ public void testEncodingWithoutConverter() throws Exception {
+ assertEquals("TestBean [42]",
+ render(beanColumn, new TestBean()).asString());
+ }
+
+ @Test
+ public void testBeanEncoding() throws Exception {
+ beanColumn.setRenderer(renderer(), converter());
+ extendedBeanColumn.setRenderer(renderer(), converter());
+
+ assertEquals("renderer(TestBean(42))",
+ render(beanColumn, new TestBean()).asString());
+ assertEquals("renderer(ExtendedBean(42, 3.14))",
+ render(beanColumn, new ExtendedBean()).asString());
+
+ assertEquals("renderer(ExtendedBean(42, 3.14))",
+ render(extendedBeanColumn, new ExtendedBean()).asString());
+ }
+
+ @Test
+ public void testNullEncoding() {
+
+ textColumn.setRenderer(new TextRenderer());
+ htmlColumn.setRenderer(new HtmlRenderer());
+ numberColumn.setRenderer(new NumberRenderer());
+ dateColumn.setRenderer(new DateRenderer());
+ buttonColumn.setRenderer(new ButtonRenderer());
+
+ assertEquals("", textColumn.getRenderer().encode(null).asString());
+ assertEquals("", htmlColumn.getRenderer().encode(null).asString());
+ assertEquals("", numberColumn.getRenderer().encode(null).asString());
+ assertEquals("", dateColumn.getRenderer().encode(null).asString());
+ assertEquals("", buttonColumn.getRenderer().encode(null).asString());
+ }
+
+ @Test
+ public void testNullEncodingWithDefault() {
+
+ textColumn.setRenderer(new TextRenderer("default value"));
+ htmlColumn.setRenderer(new HtmlRenderer("default value"));
+ numberColumn.setRenderer(
+ new NumberRenderer("%s", Locale.getDefault(), "default value"));
+ dateColumn.setRenderer(new DateRenderer("%s", "default value"));
+ buttonColumn.setRenderer(new ButtonRenderer("default value"));
+
+ assertEquals("default value",
+ textColumn.getRenderer().encode(null).asString());
+ assertEquals("default value",
+ htmlColumn.getRenderer().encode(null).asString());
+ assertEquals("default value",
+ numberColumn.getRenderer().encode(null).asString());
+ assertEquals("default value",
+ dateColumn.getRenderer().encode(null).asString());
+ assertEquals("default value",
+ buttonColumn.getRenderer().encode(null).asString());
+ }
+
+ private TestConverter converter() {
+ return new TestConverter();
+ }
+
+ private TestRenderer renderer() {
+ return new TestRenderer();
+ }
+
+ private JsonValue render(Column column, Object value) {
+ return AbstractRenderer.encodeValue(value, column.getRenderer(),
+ column.getConverter(), grid.getLocale());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java
new file mode 100644
index 0000000000..a8e6238d4b
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java
@@ -0,0 +1,129 @@
+package com.vaadin.tests.server.validation;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.BeanFieldGroup;
+import com.vaadin.tests.data.bean.BeanToValidate;
+import com.vaadin.v7.data.Validator.InvalidValueException;
+import com.vaadin.v7.data.validator.LegacyBeanValidator;
+import com.vaadin.v7.ui.LegacyField;
+
+public class BeanValidationTest {
+ @Test(expected = InvalidValueException.class)
+ public void testBeanValidationNull() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "firstname");
+ validator.validate(null);
+ }
+
+ @Test(expected = InvalidValueException.class)
+ public void testBeanValidationStringTooShort() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "firstname");
+ validator.validate("aa");
+ }
+
+ @Test
+ public void testBeanValidationStringOk() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "firstname");
+ validator.validate("aaa");
+ }
+
+ @Test(expected = InvalidValueException.class)
+ public void testBeanValidationIntegerTooSmall() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "age");
+ validator.validate(17);
+ }
+
+ @Test
+ public void testBeanValidationIntegerOk() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "age");
+ validator.validate(18);
+ }
+
+ @Test(expected = InvalidValueException.class)
+ public void testBeanValidationTooManyDigits() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "decimals");
+ validator.validate("1234.567");
+ }
+
+ @Test
+ public void testBeanValidationDigitsOk() {
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "decimals");
+ validator.validate("123.45");
+ }
+
+ @Test
+ public void testBeanValidationException_OneValidationError() {
+ InvalidValueException[] causes = null;
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "lastname");
+ try {
+ validator.validate(null);
+ } catch (InvalidValueException e) {
+ causes = e.getCauses();
+ }
+
+ Assert.assertEquals(1, causes.length);
+ }
+
+ @Test
+ public void testBeanValidationsException_TwoValidationErrors() {
+ InvalidValueException[] causes = null;
+ LegacyBeanValidator validator = new LegacyBeanValidator(
+ BeanToValidate.class, "nickname");
+ try {
+ validator.validate("A");
+ } catch (InvalidValueException e) {
+ causes = e.getCauses();
+ }
+
+ Assert.assertEquals(2, causes.length);
+ }
+
+ @Test
+ public void testBeanValidationNotAddedTwice() {
+ // See ticket #11045
+ BeanFieldGroup<BeanToValidate> fieldGroup = new BeanFieldGroup<BeanToValidate>(
+ BeanToValidate.class);
+
+ BeanToValidate beanToValidate = new BeanToValidate();
+ beanToValidate.setFirstname("a");
+ fieldGroup.setItemDataSource(beanToValidate);
+
+ LegacyField<?> nameField = fieldGroup.buildAndBind("firstname");
+ Assert.assertEquals(1, nameField.getValidators().size());
+
+ try {
+ nameField.validate();
+ } catch (InvalidValueException e) {
+ // The 1 cause is from BeanValidator, where it tells what failed
+ // 1 validation exception never gets wrapped.
+ Assert.assertEquals(1, e.getCauses().length);
+ }
+
+ // Create new, identical bean to cause duplicate validator unless #11045
+ // is fixed
+ beanToValidate = new BeanToValidate();
+ beanToValidate.setFirstname("a");
+ fieldGroup.setItemDataSource(beanToValidate);
+
+ Assert.assertEquals(1, nameField.getValidators().size());
+
+ try {
+ nameField.validate();
+ } catch (InvalidValueException e) {
+ // The 1 cause is from BeanValidator, where it tells what failed
+ // 1 validation exception never gets wrapped.
+ Assert.assertEquals(1, e.getCauses().length);
+ }
+
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/ui/TableTest.java b/compatibility-server/src/test/java/com/vaadin/ui/TableTest.java
new file mode 100644
index 0000000000..f09313f685
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/ui/TableTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2016 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.ui;
+
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.util.BeanItemContainerGenerator;
+
+public class TableTest {
+
+ Table table;
+
+ @Before
+ public void init() {
+ table = new Table();
+ }
+
+ @Test
+ public void initiallyEmpty() {
+ Assert.assertTrue(table.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClearSingleSelect() {
+ table.setContainerDataSource(
+ BeanItemContainerGenerator.createContainer(100));
+ Assert.assertTrue(table.isEmpty());
+ Object first = table.getContainerDataSource().getItemIds().iterator()
+ .next();
+ table.setValue(first);
+ Assert.assertEquals(first, table.getValue());
+ Assert.assertFalse(table.isEmpty());
+ table.clear();
+ Assert.assertEquals(null, table.getValue());
+ Assert.assertTrue(table.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClearMultiSelect() {
+ table.setMultiSelect(true);
+ table.setContainerDataSource(
+ BeanItemContainerGenerator.createContainer(100));
+
+ Assert.assertTrue(table.isEmpty());
+ Assert.assertArrayEquals(new Object[] {},
+ ((Collection) table.getValue()).toArray());
+
+ Object first = table.getContainerDataSource().getItemIds().iterator()
+ .next();
+ table.select(first);
+ Assert.assertArrayEquals(new Object[] { first },
+ ((Collection) table.getValue()).toArray());
+ Assert.assertFalse(table.isEmpty());
+
+ table.clear();
+ Assert.assertArrayEquals(new Object[] {},
+ ((Collection) table.getValue()).toArray());
+ Assert.assertTrue(table.isEmpty());
+ }
+
+}