diff options
Diffstat (limited to 'compatibility-server/src/test/java/com/vaadin/data')
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; + } +} |