org.dashbuilder.renderer.client.table.TableDisplayer.java Source code

Java tutorial

Introduction

Here is the source code for org.dashbuilder.renderer.client.table.TableDisplayer.java

Source

/**
 * Copyright (C) 2014 JBoss Inc
 *
 * 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.dashbuilder.renderer.client.table;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.gwt.cell.client.TextCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import org.dashbuilder.common.client.StringUtils;
import org.dashbuilder.dataset.DataSetLookupConstraints;
import org.dashbuilder.dataset.client.DataSetClientServiceError;
import org.dashbuilder.dataset.client.DataSetReadyCallback;
import org.dashbuilder.dataset.group.Interval;
import org.dashbuilder.displayer.ColumnSettings;
import org.dashbuilder.displayer.DisplayerAttributeDef;
import org.dashbuilder.displayer.DisplayerAttributeGroupDef;
import org.dashbuilder.displayer.DisplayerConstraints;
import org.dashbuilder.displayer.client.AbstractDisplayer;
import org.dashbuilder.dataset.DataColumn;
import org.dashbuilder.dataset.DataSet;

import org.dashbuilder.dataset.sort.SortOrder;
import org.dashbuilder.renderer.client.resources.i18n.CommonConstants;
import org.dashbuilder.renderer.client.resources.i18n.TableConstants;

import org.uberfire.ext.widgets.common.client.tables.PagedTable;

import static com.google.gwt.dom.client.BrowserEvents.CLICK;

public class TableDisplayer extends AbstractDisplayer {

    protected Widget currentSelectionWidget = null;

    protected int numberOfRows = 0;
    protected String lastOrderedColumn = null;
    protected SortOrder lastSortOrder = null;

    protected FlowPanel panel = new FlowPanel();
    protected Label label = new Label();

    protected DataSet dataSet;

    protected PagedTable<Integer> table;
    protected TableProvider tableProvider = new TableProvider();

    public TableDisplayer() {
        initWidget(panel);
    }

    public void draw() {
        if (!isDrawn()) {
            if (displayerSettings == null) {
                displayMessage(CommonConstants.INSTANCE.error() + CommonConstants.INSTANCE.error_settings_unset());
            } else if (dataSetHandler == null) {
                displayMessage(CommonConstants.INSTANCE.error() + CommonConstants.INSTANCE.error_handler_unset());
            } else {
                try {
                    String initMsg = TableConstants.INSTANCE.tableDisplayer_initializing();
                    //if (!StringUtils.isBlank(displayerSettings.getTitle())) initMsg += " '" + displayerSettings.getTitle() + "'";
                    displayMessage(initMsg + " ...");

                    lookupDataSet(0, new DataSetReadyCallback() {

                        public void callback(DataSet dataSet) {
                            Widget w = createWidget();
                            panel.clear();
                            panel.add(w);

                            // Set the id of the container panel so that the displayer can be easily located
                            // by testing tools for instance.
                            String id = getDisplayerId();
                            if (!StringUtils.isBlank(id)) {
                                panel.getElement().setId(id);
                            }

                            // Handle table pager.
                            handleTablePager();

                            // Draw done
                            afterDraw();
                        }

                        public void notFound() {
                            displayMessage(CommonConstants.INSTANCE.error()
                                    + CommonConstants.INSTANCE.error_dataset_notfound());
                        }

                        @Override
                        public boolean onError(final DataSetClientServiceError error) {
                            afterError(TableDisplayer.this, error);
                            return false;
                        }
                    });
                } catch (Exception e) {
                    displayMessage(CommonConstants.INSTANCE.error() + e.getMessage());
                }
            }
        }
    }

    /**
     * Just reload the data set and make the current Displayer redraw.
     */
    public void redraw() {
        lookupDataSet(0, new DataSetReadyCallback() {

            public void callback(DataSet dataSet) {
                tableProvider.gotoFirstPage();
                table.setRowCount(numberOfRows, true);
                table.redraw();
                redrawColumnSelectionWidget();

                // Handle table pager.
                handleTablePager();

                // Redraw done
                afterRedraw();
            }

            public void notFound() {
                displayMessage(
                        CommonConstants.INSTANCE.error() + CommonConstants.INSTANCE.error_dataset_notfound());
            }

            @Override
            public boolean onError(DataSetClientServiceError error) {
                afterError(TableDisplayer.this, error);
                return false;
            }
        });
    }

    /**
     * If only exists one page, do not show table pager.  
     */
    protected void handleTablePager() {
        if (table.getPageSize() >= table.getRowCount())
            table.pager.setVisible(false);
        else
            table.pager.setVisible(true);
    }

    /**
     * Close the displayer
     */
    public void close() {
        panel.clear();

        // Close done
        afterClose();
    }

    @Override
    public DisplayerConstraints createDisplayerConstraints() {

        DataSetLookupConstraints lookupConstraints = new DataSetLookupConstraints().setGroupAllowed(true)
                .setGroupRequired(false).setMaxColumns(-1).setMinColumns(1).setExtraColumnsAllowed(true)
                .setGroupsTitle(TableConstants.INSTANCE.tableDisplayer_groupsTitle())
                .setColumnsTitle(TableConstants.INSTANCE.tableDisplayer_columnsTitle());

        return new DisplayerConstraints(lookupConstraints).supportsAttribute(DisplayerAttributeDef.TYPE)
                .supportsAttribute(DisplayerAttributeDef.RENDERER)
                .supportsAttribute(DisplayerAttributeGroupDef.COLUMNS_GROUP)
                .supportsAttribute(DisplayerAttributeGroupDef.FILTER_GROUP)
                .supportsAttribute(DisplayerAttributeGroupDef.REFRESH_GROUP)
                .supportsAttribute(DisplayerAttributeGroupDef.GENERAL_GROUP)
                .supportsAttribute(DisplayerAttributeGroupDef.TABLE_GROUP);
    }

    /**
     * Clear the current display and show a notification message.
     */
    public void displayMessage(String msg) {
        panel.clear();
        panel.add(label);
        label.setText(msg);
    }

    /**
     * Lookup the data
     */
    public void lookupDataSet(Integer offset, final DataSetReadyCallback callback) {
        try {

            // Get the sort settings
            if (lastOrderedColumn == null) {
                String defaultSortColumn = displayerSettings.getTableDefaultSortColumnId();
                if (!StringUtils.isBlank(defaultSortColumn)) {
                    lastOrderedColumn = defaultSortColumn;
                    lastSortOrder = displayerSettings.getTableDefaultSortOrder();
                }
            }
            // Apply the sort order specified (if any)
            if (lastOrderedColumn != null) {
                sortApply(lastOrderedColumn, lastSortOrder);
            }
            // Lookup only the target rows
            dataSetHandler.limitDataSetRows(offset, displayerSettings.getTablePageSize());

            // Do the lookup
            dataSetHandler.lookupDataSet(new DataSetReadyCallback() {

                public void callback(DataSet dataSet) {
                    TableDisplayer.this.dataSet = dataSet;
                    numberOfRows = dataSet.getRowCountNonTrimmed();
                    callback.callback(dataSet);
                }

                public void notFound() {
                    callback.notFound();
                }

                @Override
                public boolean onError(DataSetClientServiceError error) {
                    callback.onError(error);
                    return false;
                }
            });
        } catch (Exception e) {
            displayMessage(CommonConstants.INSTANCE.error() + e.getMessage());
        }
    }

    protected Widget createWidget() {
        table = createTable();

        tableProvider.addDataDisplay(table);

        HTML titleHtml = new HTML();
        if (displayerSettings.isTitleVisible()) {
            titleHtml.setText(displayerSettings.getTitle());
        }

        VerticalPanel verticalPanel = new VerticalPanel();
        verticalPanel.add(titleHtml);
        verticalPanel.add(table);
        return verticalPanel;
    }

    protected PagedTable<Integer> createTable() {

        final PagedTable<Integer> pagedTable = new PagedTable<Integer>(displayerSettings.getTablePageSize());

        List<DataColumn> dataColumns = dataSet.getColumns();
        for (int i = 0; i < dataColumns.size(); i++) {
            DataColumn dataColumn = dataColumns.get(i);
            ColumnSettings columnSettings = displayerSettings.getColumnSettings(dataColumn);
            String columnName = columnSettings.getColumnName();

            Column<Integer, ?> column = createColumn(dataColumn, i);
            if (column != null) {
                column.setSortable(true);
                pagedTable.addColumn(column, columnName);
            }
        }

        pagedTable.setRowCount(numberOfRows, true);
        int height = 40 * displayerSettings.getTablePageSize() + 20;
        pagedTable.setHeight((height > (Window.getClientHeight() - this.getAbsoluteTop())
                ? (Window.getClientHeight() - this.getAbsoluteTop())
                : height) + "px");

        int tableWidth = displayerSettings.getTableWidth();
        pagedTable.setWidth(tableWidth == 0 ? dataColumns.size() * 100 + "px" : tableWidth + "px");
        pagedTable.setEmptyTableCaption(TableConstants.INSTANCE.tableDisplayer_noDataAvailable());

        if (displayerSettings.isTableSortEnabled()) {
            pagedTable.addColumnSortHandler(new ColumnSortEvent.AsyncHandler(pagedTable) {
                public void onColumnSort(ColumnSortEvent event) {
                    lastOrderedColumn = ((DataColumnCell) event.getColumn().getCell()).columnId;
                    lastSortOrder = event.isSortAscending() ? SortOrder.ASCENDING : SortOrder.DESCENDING;
                    redraw();
                }
            });
        }
        return pagedTable;
    }

    protected Column<Integer, ?> createColumn(final DataColumn column, final int columnNumber) {

        switch (column.getColumnType()) {
        case LABEL:
            return new Column<Integer, String>(new DataColumnCell(column.getId(), true)) {
                public String getValue(Integer row) {
                    Object value = dataSet.getValueAt(row, columnNumber);
                    return formatValue(value, column);
                }
            };

        case NUMBER:
        case DATE:
        case TEXT:
            return new Column<Integer, String>(new DataColumnCell(column.getId(), false)) {
                public String getValue(Integer row) {
                    Object value = dataSet.getValueAt(row, columnNumber);
                    return formatValue(value, column);
                }
            };
        }
        return null;
    }

    protected Widget createCurrentSelectionWidget() {
        if (!displayerSettings.isFilterEnabled())
            return null;

        Set<String> columnFilters = filterColumns();

        if (columnFilters.isEmpty())
            return null;

        HorizontalPanel panel = new HorizontalPanel();
        panel.getElement().setAttribute("cellpadding", "2");

        for (String columnId : columnFilters) {
            List<Interval> selectedValues = filterIntervals(columnId);
            DataColumn column = dataSet.getColumnById(columnId);
            for (Interval interval : selectedValues) {
                String formattedValue = formatInterval(interval, column);
                panel.add(new com.github.gwtbootstrap.client.ui.Label(formattedValue));
            }
        }

        Anchor anchor = new Anchor(TableConstants.INSTANCE.tableDisplayer_reset());
        panel.add(anchor);
        anchor.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                filterReset();
                redrawColumnSelectionWidget();
            }
        });
        return panel;
    }

    protected void redrawColumnSelectionWidget() {
        if (currentSelectionWidget != null)
            table.getLeftToolbar().remove(currentSelectionWidget);
        currentSelectionWidget = createCurrentSelectionWidget();
        if (currentSelectionWidget != null)
            table.getLeftToolbar().add(currentSelectionWidget);
    }

    protected class DataColumnCell extends TextCell {

        private String columnId;
        private boolean selectable = false;

        DataColumnCell(String columnId, boolean selectable) {
            this.columnId = columnId;
            this.selectable = selectable;
        }

        @Override
        public Set<String> getConsumedEvents() {
            Set<String> consumedEvents = new HashSet<String>();
            consumedEvents.add(CLICK);
            return consumedEvents;
        }

        @Override
        public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event,
                ValueUpdater<String> valueUpdater) {
            int rowIndexInPage = context.getIndex() - table.getPageStart();
            onCellSelected(columnId, selectable, rowIndexInPage);
        }
    }

    protected void onCellSelected(String columnId, boolean selectable, int rowIndex) {
        if (!selectable || !displayerSettings.isFilterEnabled())
            return;

        filterUpdate(columnId, rowIndex);
        redrawColumnSelectionWidget();
    }

    /**
     * Table data provider
     */
    protected class TableProvider extends AsyncDataProvider<Integer> {

        protected int lastOffset = -1;

        protected List<Integer> getCurrentPageRows(HasData<Integer> display) {
            final int start = ((PagedTable) display).getPageStart();
            int pageSize = ((PagedTable) display).getPageSize();
            int end = start + pageSize;
            if (end > numberOfRows)
                end = numberOfRows;

            final List<Integer> rows = new ArrayList<Integer>(end - start);
            for (int i = 0; i < end - start; i++) {
                rows.add(i);
            }
            return rows;
        }

        /**
         * Both filter & sort invoke this method from redraw()
         */
        public void gotoFirstPage() {
            // Avoid fetching the data set again
            lastOffset = 0;
            table.pager.setPage(0); // This calls internally to onRangeChanged() when the page changes

            int start = table.getPageStart();
            final List<Integer> rows = getCurrentPageRows(table);
            updateRowData(start, rows);
        }

        /**
         * Invoked from createWidget just after the data set has been fetched.
         */
        public void addDataDisplay(HasData<Integer> display) {
            // Avoid fetching the data set again
            lastOffset = 0;
            super.addDataDisplay(display); // This calls internally to onRangeChanged()
        }

        /**
         * This is invoked internally by the PagedTable on navigation actions.
         */
        protected void onRangeChanged(final HasData<Integer> display) {
            int start = ((PagedTable) display).getPageStart();
            final List<Integer> rows = getCurrentPageRows(display);

            if (lastOffset == start) {
                updateRowData(start, rows);
            } else {
                lastOffset = start;
                lookupDataSet(lastOffset, new DataSetReadyCallback() {
                    public void callback(DataSet dataSet) {
                        updateRowData(lastOffset, rows);
                    }

                    public void notFound() {
                        displayMessage(CommonConstants.INSTANCE.error()
                                + CommonConstants.INSTANCE.error_dataset_notfound());
                    }

                    public boolean onError(DataSetClientServiceError error) {
                        displayMessage(CommonConstants.INSTANCE.error() + error.getThrowable().getMessage());
                        return false;
                    }
                });
            }
        }
    }
}