package com.vaadin.tests.components.table; import java.util.HashSet; import java.util.Set; import com.vaadin.annotations.AutoGenerated; import com.vaadin.shared.ui.MarginInfo; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.Property; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.data.util.IndexedContainer; import com.vaadin.v7.ui.Table; import com.vaadin.v7.ui.Table.Align; import com.vaadin.v7.ui.Table.ColumnGenerator; public class LargeSelectionCausesNPE extends TestBase { @AutoGenerated private Table table; private static final String ID = "id"; private static final String NAME = "name"; private static final String CODE = "code"; @Override protected void setup() { addComponent(new SelectionExample()); } @Override protected String getDescription() { return "Attempting to update table contents while selection reaches beyond cache limits causes a NPE.<br>" + " Select a large amount of rows, e.g. from name2 to name262, return to the top of the table," + " then try to update the first item twice.<br>" + " Test is broken if the original values don't reappear on the second click of the button."; } @Override protected Integer getTicketNumber() { return 8519; } public class SelectionExample extends VerticalLayout { Table table = new Table(); Button button = new Button("Update the first item"); Label nameLabel = new Label(); HashSet<Object> markedRows = new HashSet<>(); Label selected = new Label(); public SelectionExample() { addComponent(table); addComponent(button); setMargin(new MarginInfo(true, false, false, false)); // Label to indicate current selection selected.setValue("No selection"); addComponent(selected); // set a style name, so we can style rows and cells table.setStyleName("iso3166"); // size table.setWidth("100%"); table.setPageLength(5); // selectable table.setSelectable(true); table.setMultiSelect(true); table.setImmediate(true); // connect data source table.setContainerDataSource(getContainer()); table.addGeneratedColumn(CODE, columnGenerator); // turn on column reordering and collapsing table.setColumnReorderingAllowed(true); table.setColumnCollapsingAllowed(true); // set column headers table.setVisibleColumns(new String[] { CODE, NAME, ID }); table.setColumnHeaders( new String[] { "DummyCode", "DummyName", "DummyId" }); // Column alignment table.setColumnAlignment(ID, Align.CENTER); // Column width table.setColumnWidth(CODE, 70); table.setColumnExpandRatio(NAME, 1); table.setColumnWidth(ID, 70); // listen for valueChange, a.k.a 'select' and update the label table.addValueChangeListener(valueChangeListener); button.setId(getTicketNumber() + "-button"); button.addClickListener(clickListener); } Table.ValueChangeListener valueChangeListener = new Table.ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { // in multiselect mode, a Set of itemIds is returned, // in singleselect mode the itemId is returned directly Set<?> value = (Set<?>) event.getProperty().getValue(); if (null == value || value.size() == 0) { selected.setValue("No selection"); } else { selected.setValue("Selected: " + table.getValue()); } } }; Button.ClickListener clickListener = new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { Property nameProperty = table.getContainerProperty(0, NAME); if (("0").equals(nameLabel.getValue())) { nameProperty.setValue(NAME + "0-version2"); nameLabel.setValue("0-version2"); } else { nameProperty.setValue(NAME + 0); nameLabel.setValue("0"); } } }; public IndexedContainer getContainer() { IndexedContainer container = new IndexedContainer(); container.addContainerProperty(NAME, String.class, null); container.addContainerProperty(ID, Integer.class, null); for (int i = 0; i < 264; i++) { String name = NAME + i; int id = i; Item item = container.addItem(id); item.getItemProperty(NAME).setValue(name); item.getItemProperty(ID).setValue(id); } container.sort(new Object[] { ID }, new boolean[] { true }); return container; } ColumnGenerator columnGenerator = new ColumnGenerator() { @Override public Object generateCell(Table source, Object itemId, Object columnId) { Label label = new Label(); label.setSizeUndefined(); label.setValue(itemId.toString()); label.setId(getTicketNumber() + "-" + itemId); if (0 == (Integer) itemId) { nameLabel = label; } return label; } }; } }