package au.com.vaadinutils.jasper.parameter; import java.util.Collection; import java.util.LinkedList; import java.util.List; import javax.persistence.metamodel.SingularAttribute; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.vaadin.addon.jpacontainer.JPAContainer; import com.vaadin.addon.jpacontainer.QueryModifierDelegate; import com.vaadin.data.Container; import com.vaadin.data.Container.Filter; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.sort.SortOrder; import com.vaadin.data.util.filter.SimpleStringFilter; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.event.SelectionEvent; import com.vaadin.event.SelectionEvent.SelectionListener; import com.vaadin.server.ErrorMessage; import com.vaadin.shared.data.sort.SortDirection; import com.vaadin.ui.Alignment; import com.vaadin.ui.Component; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.SelectionMode; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import au.com.vaadinutils.crud.CrudEntity; import au.com.vaadinutils.crud.GridHeadingPropertySet; import au.com.vaadinutils.dao.JpaBaseDao; import au.com.vaadinutils.jasper.scheduler.entities.DateParameterType; public class ReportParameterTable<T extends CrudEntity> extends ReportParameter<String> implements ReportParameterSelectionListener<T> { protected Grid grid; private Long defaultValue = null; JPAContainer<T> container = null; protected VerticalLayout layout; protected String caption; Logger logger = LogManager.getLogger(); protected SingularAttribute<T, String> displayField; public ReportParameterTable(String caption, String parameterName, Class<T> tableClass, SingularAttribute<T, String> displayField) { super(caption, parameterName); init(caption, tableClass, displayField); setSelectionMode(SelectionMode.MULTI); } public ReportParameterTable(String caption, String parameterName, Class<T> tableClass, SingularAttribute<T, String> displayField, Long defaultValue) { super(caption, parameterName); init(caption, tableClass, displayField); this.defaultValue = defaultValue; setSelectionMode(SelectionMode.MULTI); } protected void addComponentToLayout(Component comp) { layout.addComponent(comp); } void setSelectionMode(SelectionMode mode) { if (mode == SelectionMode.MULTI) { grid.setSelectionMode(SelectionMode.MULTI); grid.setSelectionModel(new Grid.MultiSelectionModel()); } else if (mode == SelectionMode.SINGLE) { grid.setSelectionMode(SelectionMode.SINGLE); grid.setSelectionModel(new Grid.SingleSelectionModel()); } else { throw new RuntimeException("SelectionMode none not supported"); } } protected void init(String caption, Class<T> tableClass, final SingularAttribute<T, String> displayField) { JpaBaseDao.getGenericDao(tableClass).flushCache(); container = createContainer(tableClass, displayField); this.displayField = displayField; layout = new VerticalLayout(); layout.setSizeFull(); this.caption = caption; TextField searchText = new TextField(); searchText.setInputPrompt("Search"); searchText.setWidth("100%"); searchText.setImmediate(true); searchText.setHeight("20"); searchText.addTextChangeListener(new TextChangeListener() { private static final long serialVersionUID = 1315710313315289836L; @Override public void textChange(TextChangeEvent event) { String value = event.getText(); removeAllContainerFilters(); if (value.length() > 0) { container.addContainerFilter(new SimpleStringFilter(displayField.getName(), value, true, false)); } } }); grid = new Grid(); grid.setImmediate(true); grid.setSizeFull(); // table.setHeight("150"); grid.setContainerDataSource(container); new GridHeadingPropertySet.Builder<T>().createColumn(caption, displayField.getName()).build().applyToGrid(grid); List<SortOrder> orders = new LinkedList<>(); orders.add(new SortOrder(displayField.getName(), SortDirection.ASCENDING)); grid.setSortOrder(orders); final Label selectionCount = new Label("0 selected"); // removed for concertina // layout.addComponent(new Label(caption)); layout.addComponent(searchText); layout.addComponent(grid); HorizontalLayout selectionLayout = new HorizontalLayout(); selectionLayout.setHeight("30"); selectionLayout.setWidth("100%"); selectionLayout.addComponent(selectionCount); selectionLayout.setComponentAlignment(selectionCount, Alignment.MIDDLE_RIGHT); layout.addComponent(selectionLayout); grid.addSelectionListener(new SelectionListener() { /** * */ private static final long serialVersionUID = 1L; @Override public void select(SelectionEvent event) { validate(); selectionCount.setValue("" + event.getSelected().size() + " selected"); } }); layout.setExpandRatio(grid, 1); // layout.setComponentAlignment(selectAll, Alignment.BOTTOM_RIGHT); } /** * overload this method to create something more than just a single entity. * * @param tableClass * @param displayField * @return */ protected JPAContainer<T> createContainer(Class<T> tableClass, final SingularAttribute<T, String> displayField) { JPAContainer<T> cont = container = JpaBaseDao.getGenericDao(tableClass).createVaadinContainer(); cont.sort(new Object[] { displayField.getName() }, new boolean[] { true }); cont.setQueryModifierDelegate(getQueryModifierDelegate()); return cont; } /** * override this method when providing a QueryModifierDelegate to filter the * rows visible in the table * * @return */ protected QueryModifierDelegate getQueryModifierDelegate() { return null; } @Override public void addSelectionListener(final ValueChangeListener listener) { grid.addSelectionListener(new SelectionListener() { /** * */ private static final long serialVersionUID = 1L; @Override public void select(SelectionEvent event) { listener.valueChange(new ValueChangeEvent() { /** * */ private static final long serialVersionUID = 1L; @Override public Property<Collection<Long>> getProperty() { return new Property<Collection<Long>>() { /** * */ private static final long serialVersionUID = 1L; @Override public Collection<Long> getValue() { return getSelectedIds(); } @Override public void setValue(Collection<Long> newValue) throws com.vaadin.data.Property.ReadOnlyException { } @Override public Class<? extends Collection<Long>> getType() { return null; } @Override public boolean isReadOnly() { return false; } @Override public void setReadOnly(boolean newStatus) { } }; } }); } }); } private Collection<Long> getSelectedIds() { Collection<Long> ids = new LinkedList<>(); for (Object id : grid.getSelectedRows()) { ids.add((Long) id); } return ids; } public void removeAllContainerFilters() { ((Container.Filterable) grid.getContainerDataSource()).removeAllContainerFilters(); } public void addContainerFilter(Filter filter) { ((Container.Filterable) grid.getContainerDataSource()).addContainerFilter(filter); } @Override public String getValue(String parameterName) { try { Collection<Object> ids = grid.getSelectedRows(); String selection = ""; for (Object id : ids) { selection += "" + id + ","; } if (selection.length() > 1) { selection = selection.substring(0, selection.length() - 1); } // supply default if emtpy if (selection.length() == 0 && defaultValue != null) { selection = "" + defaultValue; } return selection; } catch (Exception e) { logger.error("Exception while getting value(s) for " + parameterName); throw new RuntimeException(e); } } @Override public boolean validate() { validateMe(); return getValue().size() > 0; } public void validateMe() { grid.setComponentError(null); setComponentErrorForValidateListener(null); grid.setComponentError(null); setComponentErrorForValidateListener(null); Collection<Long> ids = getSelectedIds(); if (ids.size() == 0) { ErrorMessage error = new ErrorMessage() { private static final long serialVersionUID = -6437991860908562482L; @Override public ErrorLevel getErrorLevel() { return ErrorLevel.ERROR; } @Override public String getFormattedHtmlMessage() { return "You must select at least one " + caption; } }; grid.setComponentError(error); setComponentErrorForValidateListener(error); } } private void setComponentErrorForValidateListener(ErrorMessage error) { if (validateListener != null) { validateListener.setComponentError(error); } } @Override public Component getComponent() { return layout; } @Override public boolean shouldExpand() { return true; } @Override public void setDefaultValue(String defaultValue) { // TODO Auto-generated method stub } @Override public String getExpectedParameterClassName() { return String.class.getCanonicalName(); } @Override public String getDisplayValue(String parameterName) { try { Collection<Object> ids = grid.getSelectedRows(); String selection = ""; int ctr = 0; for (Object id : ids) { ctr++; final Item item = grid.getContainerDataSource().getItem(id); // we get nulls if the entity is deleted from the database after // the report parameter is saved if (item != null) { selection += "" + item.getItemProperty(displayField.getName()) + ","; } if (ctr > 2) { break; } } if (selection.length() > 1) { selection = selection.substring(0, selection.length() - 1); } if (ctr != ids.size()) { selection += " (+" + (ids.size() - ctr) + " more)"; } // supply default if emtpy if (selection.length() == 0 && defaultValue != null) { selection = "" + defaultValue; } return selection; } catch (Exception e) { for (String param : parameters) { logger.error("Exception while getting value(s) for {}, thread{}", param, Thread.currentThread().getId()); } throw new RuntimeException(e); } } @Override public void setValueAsString(String value, String parameterName) { String[] values = value.split(","); List<Long> idList = new LinkedList<>(); for (String id : values) { if (id.length() > 0) { Long intId = Long.parseLong(id); if (intId != -1) { idList.add(intId); } } } if (idList.size() > 0) { for (Long id : idList) { try { grid.select(id); } catch (IllegalArgumentException e) { logger.warn("Id doesn't exist in container"); } } } } @Override public boolean isDateField() { return false; } @Override public DateParameterType getDateParameterType() { throw new RuntimeException("Not implemented"); } @Override public Collection<Object> getValue() { return grid.getSelectedRows(); } }