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

Java tutorial

Introduction

Here is the source code for org.dashbuilder.renderer.table.client.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.table.client;

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

import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.NumberCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.cell.client.ValueUpdater;
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.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
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.DataSetReadyCallback;
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.ColumnType;
import org.dashbuilder.dataset.DataColumn;
import org.dashbuilder.dataset.DataSet;

import org.dashbuilder.dataset.sort.SortOrder;
import org.dashbuilder.renderer.table.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 {

    private Widget currentSelectionWidget = null;

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

    protected boolean drawn = false;

    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 (!drawn) {
            drawn = true;

            if (displayerSettings == null) {
                displayMessage("ERROR: DisplayerSettings property not set");
            } else if (dataSetHandler == null) {
                displayMessage("ERROR: DataSetHandler property not set");
            } 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);
                            }
                        }

                        public void notFound() {
                            displayMessage("ERROR: Data set not found.");
                        }
                    });
                } catch (Exception e) {
                    displayMessage("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();
            }

            public void notFound() {
                displayMessage("ERROR: Data set not found.");
            }
        });
    }

    @Override
    public DisplayerConstraints createDisplayerConstraints() {

        DataSetLookupConstraints lookupConstraints = new DataSetLookupConstraints().setGroupAllowed(true)
                .setGroupRequired(false).setMaxColumns(-1).setMinColumns(1).setGroupsTitle("Rows")
                .setColumnsTitle("Columns");

        return new DisplayerConstraints(lookupConstraints).supportsAttribute(DisplayerAttributeDef.TYPE)
                .supportsAttribute(DisplayerAttributeDef.RENDERER).supportsAttribute(DisplayerAttributeDef.COLUMNS)
                .supportsAttribute(DisplayerAttributeGroupDef.FILTER_GROUP)
                .supportsAttribute(DisplayerAttributeGroupDef.TITLE_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 (defaultSortColumn != null && !"".equals(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();
                }
            });
        } catch (Exception e) {
            displayMessage("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);
            String columnId = dataColumn.getId();
            String columnName = dataColumn.getName();

            Column<Integer, ?> column = createColumn(dataColumn.getColumnType(), columnId, 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 = event.getColumn().getDataStoreName();
                    lastSortOrder = event.isSortAscending() ? SortOrder.ASCENDING : SortOrder.DESCENDING;
                    redraw();
                }
            });
        }
        return pagedTable;
    }

    private Column<Integer, ?> createColumn(ColumnType columnType, String columnId, final int columnNumber) {

        switch (columnType) {
        case LABEL:
            return new Column<Integer, String>(new SelectableTextCell(columnId)) {
                public String getValue(Integer row) {
                    Object value = dataSet.getValueAt(row, columnNumber);
                    if (value == null)
                        return "---";
                    return value.toString();
                }
            };

        case TEXT:
            return new Column<Integer, String>(new TextCell()) {
                public String getValue(Integer row) {
                    Object value = dataSet.getValueAt(row, columnNumber);
                    if (value == null)
                        return "---";
                    return value.toString();
                }
            };

        case NUMBER:
            return new Column<Integer, Number>(new NumberCell(NumberFormat.getFormat("#.###"))) {
                public Number getValue(Integer row) {
                    Object value = dataSet.getValueAt(row, columnNumber);
                    if (value == null)
                        return 0;
                    return (Number) value;
                }
            };

        case DATE:
            return new Column<Integer, Date>(
                    new DateCell(DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_MEDIUM))) {
                public Date getValue(Integer row) {
                    Object value = dataSet.getValueAt(row, columnNumber);
                    if (value == null)
                        return new Date();
                    return (Date) value;
                }
            };
        }
        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<String> selectedValues = filterValues(columnId);
            for (String interval : selectedValues) {
                panel.add(new com.github.gwtbootstrap.client.ui.Label(interval));
            }
        }

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

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

    private class SelectableTextCell extends TextCell {

        private String columnId;

        private SelectableTextCell(String columnId) {
            this.columnId = columnId;
        }

        @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) {

            if (!displayerSettings.isFilterEnabled())
                return;

            filterUpdate(columnId, value);
            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("ERROR: Data set not found.");
                    }
                });
            }
        }
    }
}