aboutsummaryrefslogtreecommitdiffstats
path: root/compatibility-server/src/test/java/com/vaadin/data
diff options
context:
space:
mode:
Diffstat (limited to 'compatibility-server/src/test/java/com/vaadin/data')
-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
32 files changed, 7464 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;
+ }
+}