/******************************************************************************* * Copyright 2013 Thomas Letsch (contact@thomas-letsch.de) * * 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 org.vaadin.addons.javaee.table; import java.util.Collection; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Inject; import org.vaadin.addons.javaee.container.EntityContainer; import org.vaadin.addons.javaee.container.EntityItem; import org.vaadin.addons.javaee.fields.factory.GlobalFieldFactory; import org.vaadin.addons.javaee.i18n.TranslationKeys; import org.vaadin.addons.javaee.i18n.TranslationService; import org.vaadin.dialogs.ConfirmDialog; import com.googlecode.javaeeutils.jpa.PersistentEntity; import com.vaadin.data.Container; import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.filter.UnsupportedFilterException; import com.vaadin.server.ThemeResource; import com.vaadin.shared.ui.MultiSelectMode; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Table; import com.vaadin.ui.UI; import com.vaadin.ui.themes.Reindeer; /** * Base entity table to be subclassed for concrete implementations. * * @author thomas.letsch.de@gmail.com * * @param <ENTITY> * The persistent entity */ public abstract class BasicEntityTable<ENTITY extends PersistentEntity> extends Table implements Container.Filterable { private static final long serialVersionUID = 1L; private static final int DEFAULT_PAGE_SIZE = 5; @Inject protected TranslationService translationService; @Inject private GlobalFieldFactory tableFieldFactory; /** * Only query container if a filter is set */ protected boolean needsFilter = true; public BasicEntityTable() { } public BasicEntityTable(Class<ENTITY> entityClass) { setId(entityClass.getSimpleName() + "Table"); } protected abstract EntityContainer<ENTITY> getContainer(); /** * Can be overwritten */ protected void initColumns() { List<String> columnNames = getContainer().getPropertyNames(); initColumns(columnNames); } /** * Can be overwritten */ protected void initColumns(List<String> columnNames) { for (String columnName : columnNames) { addColumn(columnName); } } @PostConstruct protected void init() { if (needsFilter) { getContainer().needsFiltering(); } setEditable(false); setMultiSelect(false); setMultiSelectMode(MultiSelectMode.DEFAULT); setSelectable(true); setBuffered(true); setPageLength(DEFAULT_PAGE_SIZE); setCaption(translationService.getText(getContainer().getEntityClass().getSimpleName() + "s")); setTableFieldFactory(tableFieldFactory); setContainerDataSource(getContainer()); setVisibleColumns(new Object[] {}); initColumns(); } public void clear() { getContainer().clear(); } /** * Adds a generated column with a delete button for each row. Clicking on this button will cause a remove item on the underlying * container, thus deleting the entity behind the current row. */ public void addDeleteColumn() { addColumn(TranslationKeys.TITLE_DELETE, new DeleteColumnGenerator()); } public void addColumn(String name) { Class<?> type = getContainer().getType(name); addColumn(name, type); } public void addColumn(String name, Class<?> type) { addContainerProperty(name, type, null, translationService.getText(name), null, null); } public void addColumn(String name, Converter<String, ?> converter) { addColumn(name); setConverter(name, converter); } public void addColumn(String name, ColumnGenerator columnGenerator) { addGeneratedColumn(name, columnGenerator); setColumnHeader(name, translationService.getText(name)); } @Override public Long getValue() { return (Long) super.getValue(); } @Override public Collection<Filter> getContainerFilters() { return getContainer().getContainerFilters(); } @Override public void addContainerFilter(Filter filter) throws UnsupportedFilterException { getContainer().addContainerFilter(filter); } @Override public void removeContainerFilter(Filter filter) { getContainer().removeContainerFilter(filter); } @Override public void removeAllContainerFilters() { getContainer().removeAllContainerFilters(); } public boolean isAnySelected() { return getValue() != null; } public ENTITY getSelectedEntity() { EntityItem<ENTITY> item = getSelectedEntityItem(); if (item == null) { return null; } ENTITY entity = item.getEntity(); return entity; } @SuppressWarnings("unchecked") public EntityItem<ENTITY> getSelectedEntityItem() { if (getValue() == null || getValue().equals(getNullSelectionItemId())) { return null; } Long id = getValue(); EntityItem<ENTITY> item = (EntityItem<ENTITY>) getItem(id); return item; } public void removeSelectedItem() { Long id = getValue(); getContainer().removeItem(id); } public void selectFirst() { select(firstItemId()); } public void clearSelection() { select(getNullSelectionItemId()); } public void refreshCache() { getContainer().refreshCache(); } public final class DeleteColumnGenerator implements Table.ColumnGenerator { private static final long serialVersionUID = 1L; @Override public Object generateCell(Table source, final Object itemId, Object columnId) { HorizontalLayout layout = new HorizontalLayout(); layout.setMargin(false); Button deleteButton = new Button("", new DeleteButtonListener(itemId)); deleteButton.setIcon(new ThemeResource("icons/silk/delete.png")); deleteButton.setStyleName(Reindeer.BUTTON_SMALL); layout.addComponent(deleteButton); return layout; } } public final class DeleteButtonListener implements Button.ClickListener { private final Object itemId; private static final long serialVersionUID = 1L; private DeleteButtonListener(Object itemId) { this.itemId = itemId; } @Override public void buttonClick(ClickEvent event) { ConfirmDialog.show(UI.getCurrent(), translationService.getText(TranslationKeys.TITLE_DELETE), translationService.getText(TranslationKeys.MESSAGE_REALLY_DELETE), translationService.getText(TranslationKeys.YES), translationService.getText(TranslationKeys.NO), new RowDeletionConfirmListener(itemId)); } } public final class RowDeletionConfirmListener implements ConfirmDialog.Listener { private static final long serialVersionUID = 1L; private Object itemId; public RowDeletionConfirmListener(Object itemId) { this.itemId = itemId; } @Override public void onClose(ConfirmDialog dialog) { if (dialog.isConfirmed()) { getContainer().removeItem(itemId); } } } }