com.esofthead.mycollab.vaadin.ui.table.AbstractPagedBeanTable.java Source code

Java tutorial

Introduction

Here is the source code for com.esofthead.mycollab.vaadin.ui.table.AbstractPagedBeanTable.java

Source

/**
 * This file is part of mycollab-web.
 *
 * mycollab-web is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * mycollab-web is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with mycollab-web.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.esofthead.mycollab.vaadin.ui.table;

import com.esofthead.mycollab.common.TableViewField;
import com.esofthead.mycollab.common.domain.CustomViewStore;
import com.esofthead.mycollab.common.domain.NullCustomViewStore;
import com.esofthead.mycollab.common.service.CustomViewStoreService;
import com.esofthead.mycollab.core.arguments.SearchCriteria;
import com.esofthead.mycollab.core.arguments.SearchRequest;
import com.esofthead.mycollab.core.utils.XStreamJsonDeSerializer;
import com.esofthead.mycollab.spring.ApplicationContextUtil;
import com.esofthead.mycollab.vaadin.AppContext;
import com.esofthead.mycollab.vaadin.events.PagableHandler;
import com.esofthead.mycollab.vaadin.events.SelectableItemHandler;
import com.esofthead.mycollab.vaadin.ui.ButtonLink;
import com.vaadin.data.Container;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.*;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Table.ColumnGenerator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 
 * @author MyCollab Ltd.
 * @since 2.0
 * 
 * @param <S>
 * @param <B>
 */
public abstract class AbstractPagedBeanTable<S extends SearchCriteria, B> extends VerticalLayout
        implements IPagedBeanTable<S, B> {
    private static final long serialVersionUID = 1L;

    private static final Logger LOG = LoggerFactory.getLogger(AbstractPagedBeanTable.class);

    protected int displayNumItems = SearchRequest.DEFAULT_NUMBER_SEARCH_ITEMS;
    protected Collection<B> currentListData;

    protected HorizontalLayout pageManagement;

    protected boolean isAscending = true;
    protected Object sortColumnId;

    protected SearchRequest<S> searchRequest;
    protected int currentPage = 1;
    protected int totalPage = 1;
    protected int currentViewCount;
    protected int totalCount;

    protected Table tableItem;
    protected CssLayout controlBarWrapper;

    protected Set<SelectableItemHandler<B>> selectableHandlers;
    protected Set<PagableHandler> pagableHandlers;

    protected final Class<B> type;

    private TableViewField requiredColumn;
    private List<TableViewField> displayColumns;
    private List<TableViewField> defaultSelectedColumns;

    protected final Map<Object, ColumnGenerator> columnGenerators = new HashMap<>();

    public AbstractPagedBeanTable(Class<B> type, List<TableViewField> displayColumns) {
        this(type, null, displayColumns);
    }

    public AbstractPagedBeanTable(Class<B> type, TableViewField requiredColumn,
            List<TableViewField> displayColumns) {
        this(type, null, requiredColumn, displayColumns);
    }

    @SuppressWarnings("unchecked")
    public AbstractPagedBeanTable(Class<B> type, String viewId, TableViewField requiredColumn,
            List<TableViewField> displayColumns) {
        if (viewId != null) {
            CustomViewStoreService customViewStoreService = ApplicationContextUtil
                    .getSpringBean(CustomViewStoreService.class);
            CustomViewStore viewLayoutDef = customViewStoreService.getViewLayoutDef(AppContext.getAccountId(),
                    AppContext.getUsername(), viewId);
            if (!(viewLayoutDef instanceof NullCustomViewStore)) {
                try {
                    List<TableViewField> selectedColumns = (List<TableViewField>) XStreamJsonDeSerializer
                            .fromJson(viewLayoutDef.getViewinfo());
                    // @HACK: the problem in deserialize json cause the list of
                    // list
                    this.displayColumns = (List<TableViewField>) selectedColumns.get(0);
                } catch (Exception e) {
                    LOG.error("Error", e);
                    this.displayColumns = displayColumns;
                }
            } else {
                this.displayColumns = displayColumns;
            }
        } else {
            this.displayColumns = displayColumns;
        }

        this.defaultSelectedColumns = displayColumns;
        this.requiredColumn = requiredColumn;
        this.type = type;

        this.setStyleName("list-view");
    }

    public void setDisplayColumns(List<TableViewField> viewFields) {
        this.displayColumns = viewFields;
        displayTableColumns();
        this.markAsDirty();
    }

    private void displayTableColumns() {
        List<String> visibleColumnsCol = new ArrayList<>();
        List<String> columnHeadersCol = new ArrayList<>();

        if (requiredColumn != null) {
            visibleColumnsCol.add(requiredColumn.getField());
            columnHeadersCol.add(AppContext.getMessage(requiredColumn.getDescKey()));
            this.tableItem.setColumnWidth(requiredColumn.getField(), requiredColumn.getDefaultWidth());
        }

        for (int i = 0; i < displayColumns.size(); i++) {
            TableViewField viewField = displayColumns.get(i);
            visibleColumnsCol.add(viewField.getField());
            columnHeadersCol.add(AppContext.getMessage(viewField.getDescKey()));

            if (i == 0) {
                this.tableItem.setColumnExpandRatio(viewField.getField(), 1.0f);
            } else {
                this.tableItem.setColumnWidth(viewField.getField(), viewField.getDefaultWidth());
            }
        }

        String[] visibleColumns = visibleColumnsCol.toArray(new String[visibleColumnsCol.size()]);
        String[] columnHeaders = columnHeadersCol.toArray(new String[columnHeadersCol.size()]);

        this.tableItem.setVisibleColumns(visibleColumns);
        this.tableItem.setColumnHeaders(columnHeaders);
    }

    @Override
    public void addSelectableItemHandler(final SelectableItemHandler<B> handler) {
        if (this.selectableHandlers == null) {
            this.selectableHandlers = new HashSet<>();
        }
        this.selectableHandlers.add(handler);
    }

    @Override
    public int currentViewCount() {
        return this.currentViewCount;
    }

    @Override
    public int totalItemsCount() {
        return this.totalCount;
    }

    @Override
    public void addPagableHandler(final PagableHandler handler) {
        if (this.pagableHandlers == null) {
            this.pagableHandlers = new HashSet<>();
        }
        this.pagableHandlers.add(handler);

    }

    @Override
    public Collection<B> getCurrentDataList() {
        return currentListData;
    }

    public void setCurrentDataList(Collection<B> list) {
        this.currentListData = list;
        this.currentViewCount = list.size();
        createTable();
    }

    @Override
    public void addTableListener(TableClickListener listener) {
        addListener(TableClickEvent.TABLE_CLICK_IDENTIFIER, TableClickEvent.class, listener,
                TableClickListener.itemClickMethod);
    }

    protected void fireTableEvent(final TableClickEvent event) {
        fireEvent(event);
    }

    @Override
    public void addGeneratedColumn(final Object id, final ColumnGenerator generatedColumn) {
        this.columnGenerators.put(id, generatedColumn);
    }

    @Override
    public void setSearchCriteria(final S searchCriteria) {
        this.searchRequest = new SearchRequest<>(searchCriteria, this.currentPage, this.displayNumItems);
        this.doSearch();
    }

    public void setDisplayNumItems(int displayNumItems) {
        this.displayNumItems = displayNumItems;
    }

    @Override
    @SuppressWarnings("unchecked")
    public B getBeanByIndex(final Object itemId) {
        final Container container = this.tableItem.getContainerDataSource();
        final BeanItem<B> item = (BeanItem<B>) container.getItem(itemId);
        return item == null ? null : item.getBean();
    }

    @Override
    public void refresh() {
        this.doSearch();
    }

    protected void pageChange(final int currentPage) {
        if (this.searchRequest != null) {
            this.currentPage = currentPage;
            this.searchRequest.setCurrentPage(currentPage);
            this.doSearch();

            if (this.pagableHandlers != null) {
                for (final PagableHandler handler : this.pagableHandlers) {
                    handler.move(currentPage);
                }
            }
        }
    }

    public void fireSelectItemEvent(final B item) {
        if (this.selectableHandlers != null) {
            for (final SelectableItemHandler<B> handler : this.selectableHandlers) {
                handler.onSelect(item);
            }
        }
    }

    private CssLayout createControls() {
        this.controlBarWrapper = new CssLayout();
        this.controlBarWrapper.setStyleName("listControl");
        this.controlBarWrapper.setWidth("100%");

        final HorizontalLayout controlBar = new HorizontalLayout();
        controlBar.setWidth("100%");
        this.controlBarWrapper.addComponent(controlBar);

        this.pageManagement = new HorizontalLayout();

        // defined layout here ---------------------------

        if (this.currentPage > 1) {
            final Button firstLink = new ButtonLink("1", new ClickListener() {
                private static final long serialVersionUID = 1L;

                @Override
                public void buttonClick(final ClickEvent event) {
                    AbstractPagedBeanTable.this.pageChange(1);
                }
            }, false);
            firstLink.addStyleName("buttonPaging");
            this.pageManagement.addComponent(firstLink);
        }
        if (this.currentPage >= 5) {
            final Label ss1 = new Label("...");
            ss1.addStyleName("buttonPaging");
            this.pageManagement.addComponent(ss1);
        }

        if (this.currentPage > 3) {
            final Button previous2 = new ButtonLink("" + (this.currentPage - 2), new ClickListener() {
                private static final long serialVersionUID = 1L;

                @Override
                public void buttonClick(final ClickEvent event) {
                    AbstractPagedBeanTable.this.pageChange(AbstractPagedBeanTable.this.currentPage - 2);
                }
            }, false);
            previous2.addStyleName("buttonPaging");
            this.pageManagement.addComponent(previous2);
        }
        if (this.currentPage > 2) {
            final Button previous1 = new ButtonLink("" + (this.currentPage - 1), new ClickListener() {
                private static final long serialVersionUID = 1L;

                @Override
                public void buttonClick(final ClickEvent event) {
                    AbstractPagedBeanTable.this.pageChange(AbstractPagedBeanTable.this.currentPage - 1);
                }
            }, false);
            previous1.addStyleName("buttonPaging");
            this.pageManagement.addComponent(previous1);
        }
        // Here add current ButtonLink
        final Button current = new ButtonLink("" + this.currentPage, new ClickListener() {
            private static final long serialVersionUID = 1L;

            @Override
            public void buttonClick(final ClickEvent event) {
                AbstractPagedBeanTable.this.pageChange(AbstractPagedBeanTable.this.currentPage);
            }
        }, false);
        current.addStyleName("buttonPaging");
        current.addStyleName("buttonPagingcurrent");

        this.pageManagement.addComponent(current);
        final int range = this.totalPage - this.currentPage;
        if (range >= 1) {
            final Button next1 = new ButtonLink("" + (this.currentPage + 1), new ClickListener() {
                private static final long serialVersionUID = 1L;

                @Override
                public void buttonClick(final ClickEvent event) {
                    AbstractPagedBeanTable.this.pageChange(AbstractPagedBeanTable.this.currentPage + 1);
                }
            }, false);
            next1.addStyleName("buttonPaging");
            this.pageManagement.addComponent(next1);
        }
        if (range >= 2) {
            final Button next2 = new ButtonLink("" + (this.currentPage + 2), new ClickListener() {
                private static final long serialVersionUID = 1L;

                @Override
                public void buttonClick(final ClickEvent event) {
                    AbstractPagedBeanTable.this.pageChange(AbstractPagedBeanTable.this.currentPage + 2);
                }
            }, false);
            next2.addStyleName("buttonPaging");
            this.pageManagement.addComponent(next2);
        }
        if (range >= 4) {
            final Label ss2 = new Label("...");
            ss2.addStyleName("buttonPaging");
            this.pageManagement.addComponent(ss2);
        }
        if (range >= 3) {
            final Button last = new ButtonLink("" + this.totalPage, new ClickListener() {
                private static final long serialVersionUID = 1L;

                @Override
                public void buttonClick(final ClickEvent event) {
                    AbstractPagedBeanTable.this.pageChange(AbstractPagedBeanTable.this.totalPage);
                }
            }, false);
            last.addStyleName("buttonPaging");
            this.pageManagement.addComponent(last);
        }

        this.pageManagement.setWidth(null);
        this.pageManagement.setSpacing(true);
        controlBar.addComponent(this.pageManagement);
        controlBar.setComponentAlignment(this.pageManagement, Alignment.MIDDLE_RIGHT);

        return this.controlBarWrapper;
    }

    abstract protected int queryTotalCount();

    abstract protected List<B> queryCurrentData();

    protected void doSearch() {
        this.totalCount = this.queryTotalCount();
        this.totalPage = (this.totalCount - 1) / this.searchRequest.getNumberOfItems() + 1;
        if (this.searchRequest.getCurrentPage() > this.totalPage) {
            this.searchRequest.setCurrentPage(this.totalPage);
        }

        if (this.totalPage > 1) {
            // Define button layout
            if (this.controlBarWrapper != null) {
                this.removeComponent(this.controlBarWrapper);
            }
            this.addComponent(this.createControls());
        } else {
            if (this.getComponentCount() == 2) {
                this.removeComponent(this.getComponent(1));
            }
        }

        this.currentListData = this.queryCurrentData();
        this.currentViewCount = this.currentListData.size();

        createTable();
    }

    private void createTable() {
        this.tableItem = new Table();
        this.tableItem.setWidth("100%");
        this.tableItem.addStyleName("striped");
        this.tableItem.setSortEnabled(false);

        // set column generator
        for (final Object propertyId : this.columnGenerators.keySet()) {
            this.tableItem.addGeneratedColumn(propertyId, this.columnGenerators.get(propertyId));
        }

        if (StringUtils.isNotBlank((String) this.sortColumnId)) {
            this.tableItem.setColumnIcon(this.sortColumnId,
                    this.isAscending ? FontAwesome.CARET_DOWN : FontAwesome.CARET_UP);
        }

        this.tableItem.addHeaderClickListener(new Table.HeaderClickListener() {
            private static final long serialVersionUID = 1L;

            @Override
            public void headerClick(final Table.HeaderClickEvent event) {
                final String propertyId = (String) event.getPropertyId();

                if (propertyId.equals("selected")) {
                    return;
                }

                if (AbstractPagedBeanTable.this.searchRequest != null) {
                    AbstractPagedBeanTable.this.sortColumnId = propertyId;

                    final S searchCriteria = AbstractPagedBeanTable.this.searchRequest.getSearchCriteria();
                    if (searchCriteria.getOrderByField() == null) {
                        searchCriteria.setOrderByField(propertyId);
                        searchCriteria.setSortDirection(SearchCriteria.DESC);
                        AbstractPagedBeanTable.this.isAscending = false;
                    } else if (propertyId.equals(searchCriteria.getOrderByField())) {
                        AbstractPagedBeanTable.this.isAscending = !AbstractPagedBeanTable.this.isAscending;
                        searchCriteria.setSortDirection(
                                searchCriteria.getSortDirection().equals(SearchCriteria.ASC) ? SearchCriteria.DESC
                                        : SearchCriteria.ASC);
                    } else {
                        searchCriteria.setOrderByField(propertyId);
                        searchCriteria.setSortDirection(SearchCriteria.DESC);
                        AbstractPagedBeanTable.this.isAscending = false;
                    }

                    AbstractPagedBeanTable.this.setSearchCriteria(searchCriteria);
                }
            }
        });

        final BeanItemContainer<B> container = new BeanItemContainer<>(this.type, this.currentListData);
        this.tableItem.setPageLength(0);
        this.tableItem.setContainerDataSource(container);
        displayTableColumns();
        this.tableItem.setWidth("100%");

        if (this.getComponentCount() > 0) {
            final Component component0 = this.getComponent(0);
            if (component0 instanceof Table) {
                this.replaceComponent(component0, tableItem);
            } else {
                this.addComponent(tableItem, 0);
            }
        } else {
            this.addComponent(tableItem, 0);
        }

    }

    public Table getTable() {
        return tableItem;
    }

    public List<TableViewField> getDefaultSelectedColumns() {
        return defaultSelectedColumns;
    }

    public List<TableViewField> getDisplayColumns() {
        return displayColumns;
    }

    public Object[] getVisibleColumns() {
        return tableItem.getVisibleColumns();
    }
}