org.roda.wui.client.common.lists.utils.AsyncTableCell.java Source code

Java tutorial

Introduction

Here is the source code for org.roda.wui.client.common.lists.utils.AsyncTableCell.java

Source

/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE file at the root of the source
 * tree and available online at
 *
 * https://github.com/keeps/roda
 */
package org.roda.wui.client.common.lists.utils;

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

import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.v2.index.IndexResult;
import org.roda.core.data.v2.index.IsIndexed;
import org.roda.core.data.v2.index.facet.FacetFieldResult;
import org.roda.core.data.v2.index.facet.FacetParameter;
import org.roda.core.data.v2.index.facet.FacetValue;
import org.roda.core.data.v2.index.facet.Facets;
import org.roda.core.data.v2.index.filter.Filter;
import org.roda.core.data.v2.index.filter.OneOfManyFilterParameter;
import org.roda.core.data.v2.index.select.SelectedItems;
import org.roda.core.data.v2.index.select.SelectedItemsFilter;
import org.roda.core.data.v2.index.select.SelectedItemsList;
import org.roda.core.data.v2.index.sort.SortParameter;
import org.roda.core.data.v2.index.sort.Sorter;
import org.roda.core.data.v2.index.sublist.Sublist;
import org.roda.wui.client.browse.BrowserService;
import org.roda.wui.client.common.actions.Actionable;
import org.roda.wui.client.common.lists.pagination.ListSelectionState;
import org.roda.wui.client.common.lists.pagination.ListSelectionUtils;
import org.roda.wui.client.common.popup.CalloutPopup;
import org.roda.wui.client.common.popup.CalloutPopup.CalloutPosition;
import org.roda.wui.client.common.utils.AsyncCallbackUtils;
import org.roda.wui.client.common.utils.HtmlSnippetUtils;
import org.roda.wui.client.common.utils.StringUtils;
import org.roda.wui.common.client.ClientLogger;
import org.roda.wui.common.client.tools.FacetUtils;
import org.roda.wui.common.client.tools.RestUtils;
import org.roda.wui.common.client.widgets.MyCellTableResources;
import org.roda.wui.common.client.widgets.wcag.AccessibleCellTable;
import org.roda.wui.common.client.widgets.wcag.AccessibleSimplePager;
import org.roda.wui.common.client.widgets.wcag.AcessibleCheckboxCell;

import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.AsyncHandler;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.cellview.client.SafeHtmlHeader;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.CellPreviewEvent.Handler;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.SingleSelectionModel;

import config.i18n.client.ClientMessages;

public abstract class AsyncTableCell<T extends IsIndexed, O> extends FlowPanel
        implements HasValueChangeHandlers<IndexResult<T>> {

    private static final ClientMessages messages = GWT.create(ClientMessages.class);

    private final Class<T> classToReturn;
    private final O object;

    private final MyAsyncDataProvider<T> dataProvider;
    private final SingleSelectionModel<T> selectionModel;
    private final AsyncHandler columnSortHandler;

    private final AccessibleSimplePager resultsPager;
    private final RodaPageSizePager pageSizePager;
    private Button csvDownloadButton;
    private Button actionsButton;
    private final CellTable<T> display;

    private FlowPanel selectAllPanel;
    private FlowPanel selectAllPanelBody;
    private Label selectAllLabel;
    private CheckBox selectAllCheckBox;

    private Column<T, Boolean> selectColumn;
    private Set<T> selected = new HashSet<>();
    private final List<CheckboxSelectionListener<T>> listeners = new ArrayList<>();

    private Filter filter;
    private boolean justActive;
    private Facets facets;
    private boolean selectable;

    private List<String> fieldsToReturn;

    private final ClientLogger logger = new ClientLogger(getClass().getName());

    private int initialPageSize = 20;
    private int pageSizeIncrement = 100;

    private Timer autoUpdateTimer = null;
    private int autoUpdateTimerMillis = 0;

    private IndexResult<T> result;

    private Actionable<T> actionable = null;
    private final CalloutPopup actionsPopup = new CalloutPopup();

    public AsyncTableCell(Class<T> classToReturn, List<String> fieldsToReturn) {
        this(classToReturn, null, false, null, null, false, 20, 100, null, fieldsToReturn);
    }

    public AsyncTableCell(Class<T> classToReturn, Filter filter, boolean justActive, Facets facets, String summary,
            boolean selectable, O object, List<String> fieldsToReturn) {
        this(classToReturn, filter, justActive, facets, summary, selectable, 20, 100, object, fieldsToReturn);
    }

    public AsyncTableCell(final Class<T> classToReturn, final Filter filter, final boolean justActive,
            final Facets facets, final String summary, final boolean selectable, final int initialPageSize,
            final int pageSizeIncrement, final O object, List<String> fieldsToReturn) {
        super();

        this.classToReturn = classToReturn;
        this.initialPageSize = initialPageSize;
        this.pageSizeIncrement = pageSizeIncrement;
        this.object = object;

        final String notNullSummary = StringUtils.isNotBlank(summary) ? summary : "summary" + Random.nextInt(1000);

        this.filter = filter;
        this.justActive = justActive;
        this.facets = facets;
        this.selectable = selectable;

        this.fieldsToReturn = fieldsToReturn;

        display = new AccessibleCellTable<>(getInitialPageSize(),
                (MyCellTableResources) GWT.create(MyCellTableResources.class), getKeyProvider(), summary);
        display.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED);
        display.setLoadingIndicator(new HTML(HtmlSnippetUtils.LOADING));

        configure(display);

        this.dataProvider = new MyAsyncDataProvider<T>(display, fieldsToReturn, new IndexResultDataProvider<T>() {

            @Override
            public void getData(Sublist sublist, Sorter sorter, List<String> fieldsToReturn,
                    final AsyncCallback<IndexResult<T>> callback) {
                AsyncTableCell.this.getData(AsyncTableCell.this.getFilter(), sublist, sorter, fieldsToReturn,
                        new AsyncCallback<IndexResult<T>>() {

                            @Override
                            public void onFailure(Throwable caught) {
                                callback.onFailure(caught);

                            }

                            @Override
                            public void onSuccess(IndexResult<T> result) {
                                setResult(result);
                                callback.onSuccess(result);
                            }
                        });
            }

            @Override
            public Sorter getSorter(ColumnSortList columnSortList) {
                return AsyncTableCell.this.getSorter(columnSortList);
            }
        }) {

            @Override
            protected void fireChangeEvent(IndexResult<T> result) {
                ValueChangeEvent.fire(AsyncTableCell.this, result);
            }
        };

        dataProvider.addDataDisplay(display);

        resultsPager = new AccessibleSimplePager(AccessibleSimplePager.TextLocation.LEFT,
                (SimplePager.Resources) GWT.create(SimplePager.Resources.class), false, initialPageSize, false,
                false, (SimplePager.ImageButtonsConstants) GWT.create(SimplePager.ImageButtonsConstants.class));
        resultsPager.setDisplay(display);

        pageSizePager = new RodaPageSizePager(getPageSizePagerIncrement());
        pageSizePager.setDisplay(display);

        csvDownloadButton = new Button(messages.tableDownloadCSV());
        csvDownloadButton.addStyleName("btn btn-link csvDownloadButton");

        actionsButton = new Button(messages.tableAction());
        actionsButton.addStyleName("btn btn-link actionsButton");
        actionsButton.setVisible(actionable != null);

        createSelectAllPanel();

        add(selectAllPanel);
        add(display);
        add(resultsPager);
        add(pageSizePager);
        add(csvDownloadButton);
        add(actionsButton);

        csvDownloadButton.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                RestUtils.requestCSVExport(getClassToReturn(), getFilter(), dataProvider.getSorter(),
                        dataProvider.getSublist(), getFacets(), getJustActive(), false, notNullSummary + ".csv");
            }
        });

        actionsButton.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                showActions();
            }
        });

        selectionModel = new SingleSelectionModel<>(getKeyProvider());

        Handler<T> selectionEventManager = getSelectionEventManager();
        if (selectionEventManager != null) {
            display.setSelectionModel(selectionModel, selectionEventManager);
        } else {
            display.setSelectionModel(selectionModel);
        }

        columnSortHandler = new AsyncHandler(display);
        display.addColumnSortHandler(columnSortHandler);

        addStyleName("my-asyncdatagrid");
        resultsPager.addStyleName("my-asyncdatagrid-pager-results");
        pageSizePager.addStyleName("my-asyncdatagrid-pager-pagesize");
        display.addStyleName("my-asyncdatagrid-display");

        addValueChangeHandler(new ValueChangeHandler<IndexResult<T>>() {
            @Override
            public void onValueChange(ValueChangeEvent<IndexResult<T>> event) {
                selected = new HashSet<>();
                hideSelectAllPanel();
            }
        });

        updateEmptyTableWidget();
    }

    private void updateEmptyTableWidget() {
        if (FacetUtils.hasSelected(getFacets())) {
            FlowPanel layout = new FlowPanel();
            Label l = new Label(messages.noItemsToDisplayButFacetsActive());
            Button resetFacets = new Button(messages.disableFacets());

            layout.addStyleName("table-empty");
            resetFacets.addStyleName("table-empty-clear-facets btn btn-primary btn-ban");

            resetFacets.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    FacetUtils.clearFacets(getFacets());
                    refresh();
                }
            });
            layout.add(l);
            layout.add(resetFacets);
            display.setEmptyTableWidget(layout);
        } else {
            Label layout = new Label(messages.noItemsToDisplay());
            layout.addStyleName("table-empty");
            display.setEmptyTableWidget(layout);
        }
    }

    private void configure(final CellTable<T> display) {
        if (selectable) {
            selectColumn = new Column<T, Boolean>(new AcessibleCheckboxCell(true, false)) {
                @Override
                public Boolean getValue(T object) {
                    return selected.contains(object);
                }
            };

            selectColumn.setFieldUpdater(new FieldUpdater<T, Boolean>() {
                @Override
                public void update(int index, T object, Boolean isSelected) {
                    if (isSelected) {
                        selected.add(object);
                    } else {
                        selected.remove(object);
                    }

                    // update header
                    display.redrawHeaders();
                    fireOnCheckboxSelectionChanged();
                }
            });

            Header<Boolean> selectHeader = new Header<Boolean>(new AcessibleCheckboxCell(true, true)) {

                @Override
                public Boolean getValue() {
                    Boolean ret;

                    if (selected.isEmpty()) {
                        ret = false;
                    } else if (selected.containsAll(getVisibleItems())) {
                        ret = true;
                        showSelectAllPanel();
                    } else {
                        // some are selected
                        ret = false;
                        hideSelectAllPanel();
                    }

                    return ret;
                }
            };

            selectHeader.setUpdater(new ValueUpdater<Boolean>() {

                @Override
                public void update(Boolean value) {
                    if (value) {
                        selected.addAll(getVisibleItems());
                        showSelectAllPanel();
                    } else {
                        selected.clear();
                        hideSelectAllPanel();
                    }
                    redraw();
                    fireOnCheckboxSelectionChanged();
                }
            });

            display.addColumn(selectColumn, selectHeader);
            display.setColumnWidth(selectColumn, "45px");
        }
        configureDisplay(display);
    }

    public Class<T> getClassToReturn() {
        return classToReturn;
    }

    protected abstract void configureDisplay(CellTable<T> display);

    protected int getInitialPageSize() {
        return initialPageSize;
    }

    protected ProvidesKey<T> getKeyProvider() {
        return new ProvidesKey<T>() {

            @Override
            public Object getKey(T item) {
                return item.getUUID();
            }
        };
    }

    private void getData(Filter filter, Sublist sublist, Sorter sorter, List<String> fieldsToReturn,
            AsyncCallback<IndexResult<T>> callback) {
        if (filter == null) {
            callback.onSuccess(null);
        } else {
            getData(sublist, sorter, fieldsToReturn, callback);
        }
    }

    protected void getData(Sublist sublist, Sorter sorter, List<String> fieldsToReturn,
            AsyncCallback<IndexResult<T>> callback) {
        BrowserService.Util.getInstance().find(getClassToReturn().getName(), getFilter(), sorter, sublist,
                getFacets(), LocaleInfo.getCurrentLocale().getLocaleName(), getJustActive(), fieldsToReturn,
                callback);
    }

    protected abstract Sorter getSorter(ColumnSortList columnSortList);

    public Sorter getSorter() {
        return dataProvider.getSorter();
    }

    protected int getPageSizePagerIncrement() {
        return pageSizeIncrement;
    }

    protected CellPreviewEvent.Handler<T> getSelectionEventManager() {
        if (selectable) {
            return DefaultSelectionEventManager.<T>createBlacklistManager(0);
        } else {
            return null;
        }
    }

    public SingleSelectionModel<T> getSelectionModel() {
        return selectionModel;
    }

    public void refresh() {
        selected = new HashSet<>();
        hideSelectAllPanel();
        display.setVisibleRangeAndClearData(new Range(0, getInitialPageSize()), true);
        getSelectionModel().clear();
        updateEmptyTableWidget();
    }

    public void update() {
        dataProvider.update(fieldsToReturn);
    }

    public void autoUpdate(int periodMillis) {
        if (autoUpdateTimer != null) {
            autoUpdateTimer.cancel();
        }

        autoUpdateTimer = new Timer() {

            @Override
            public void run() {
                dataProvider.update(fieldsToReturn, new AsyncCallback<Void>() {

                    @Override
                    public void onFailure(Throwable caught) {
                        // disable auto-update
                        autoUpdateTimer.cancel();
                    }

                    @Override
                    public void onSuccess(Void result) {
                        // do nothing
                    }
                });
            }
        };

        autoUpdateTimerMillis = periodMillis;
        if (this.isAttached()) {
            autoUpdateTimer.scheduleRepeating(periodMillis);
        }

    }

    @Override
    protected void onDetach() {
        if (autoUpdateTimer != null) {
            autoUpdateTimer.cancel();
        }
        super.onDetach();
    }

    @Override
    protected void onLoad() {
        if (autoUpdateTimer != null && autoUpdateTimerMillis > 0 && !autoUpdateTimer.isRunning()) {
            autoUpdateTimer.scheduleRepeating(autoUpdateTimerMillis);
        }
        super.onLoad();
    }

    public void redraw() {
        display.redraw();
    }

    public Filter getFilter() {
        return filter;
    }

    public boolean getJustActive() {
        return justActive;
    }

    public void setJustActive(boolean justActive) {
        this.justActive = justActive;
        refresh();
    }

    public void setFilter(Filter filter) {
        this.filter = filter;
        refresh();
    }

    public Facets getFacets() {
        return facets;
    }

    public void setFacets(Facets facets) {
        this.facets = facets;
        refresh();
    }

    public void set(Filter filter, boolean justActive, Facets facets) {
        this.filter = filter;
        this.justActive = justActive;
        this.facets = facets;
        refresh();
    }

    @Override
    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<IndexResult<T>> handler) {
        return addHandler(handler, ValueChangeEvent.getType());
    }

    public List<T> getVisibleItems() {
        return display.getVisibleItems();
    }

    protected Sorter createSorter(ColumnSortList columnSortList,
            Map<Column<T, ?>, List<String>> columnSortingKeyMap) {
        Sorter sorter = new Sorter();
        for (int i = 0; i < columnSortList.size(); i++) {
            ColumnSortInfo columnSortInfo = columnSortList.get(i);

            List<String> sortParameterKeys = columnSortingKeyMap.get(columnSortInfo.getColumn());

            if (sortParameterKeys != null) {
                for (String sortParameterKey : sortParameterKeys) {
                    sorter.add(new SortParameter(sortParameterKey, !columnSortInfo.isAscending()));
                }
            } else {
                logger.warn("Selecting a sorter that is not mapped");
            }
        }
        return sorter;
    }

    public void nextItemSelection() {
        nextItemSelection(false);
    }

    public void nextItemSelection(boolean nextPageJump) {
        if (getSelectionModel().getSelectedObject() != null) {
            T selectedItem = getSelectionModel().getSelectedObject();
            int selectedIndex = getVisibleItems().indexOf(selectedItem);

            if (nextPageJump) {
                if (selectedIndex == -1) {
                    getSelectionModel().setSelected(getVisibleItems().get(0), true);
                } else {
                    getSelectionModel().setSelected(getVisibleItems().get(selectedIndex + 1), true);
                }
            } else {
                if (selectedIndex < getVisibleItems().size() - 1) {
                    getSelectionModel().setSelected(getVisibleItems().get(selectedIndex + 1), true);
                }
            }
        } else {
            getSelectionModel().setSelected(getVisibleItems().get(0), true);
        }
    }

    public void previousItemSelection() {
        previousItemSelection(false);
    }

    public void previousItemSelection(boolean previousPageJump) {
        if (getSelectionModel().getSelectedObject() != null) {
            T selectedItem = getSelectionModel().getSelectedObject();
            int selectedIndex = getVisibleItems().indexOf(selectedItem);

            if (previousPageJump) {
                if (selectedIndex == -1) {
                    getSelectionModel().setSelected(getVisibleItems().get(getVisibleItems().size() - 1), true);
                } else {
                    getSelectionModel().setSelected(getVisibleItems().get(selectedIndex - 1), true);
                }
            } else {
                if (selectedIndex > 0) {
                    getSelectionModel().setSelected(getVisibleItems().get(selectedIndex - 1), true);
                }
            }
        } else {
            getSelectionModel().setSelected(getVisibleItems().get(0), true);
        }
    }

    public boolean nextPageOnNextFile() {
        boolean nextPage = false;
        if (getSelectionModel().getSelectedObject() != null) {
            T selectedItem = getSelectionModel().getSelectedObject();
            if (getVisibleItems().indexOf(selectedItem) == (resultsPager.getPageSize() - 1)
                    && resultsPager.hasNextPage()) {
                nextPage = true;
            }
        }
        return nextPage;
    }

    public boolean previousPageOnPreviousFile() {
        boolean previousPage = false;
        if (getSelectionModel().getSelectedObject() != null) {
            T selectedItem = getSelectionModel().getSelectedObject();
            if (getVisibleItems().indexOf(selectedItem) == 0 && resultsPager.hasPreviousPage()) {
                previousPage = true;
            }
        }
        return previousPage;
    }

    public void nextPage() {
        resultsPager.nextPage();
    }

    public void previousPage() {
        resultsPager.previousPage();
    }

    public boolean isSelectable() {
        return selectable;
    }

    public void setSelectable(boolean selectable) {
        this.selectable = selectable;
    }

    public SelectedItems<T> getSelected() {
        SelectedItems<T> ret;
        if (isAllSelected()) {
            Filter filterPlusFacets = new Filter(getFilter());
            if (getFacets() != null) {
                for (FacetParameter facetParameter : getFacets().getParameters().values()) {
                    if (!facetParameter.getValues().isEmpty()) {
                        filterPlusFacets.add(
                                new OneOfManyFilterParameter(facetParameter.getName(), facetParameter.getValues()));
                    }
                }
            }

            ret = new SelectedItemsFilter<>(filterPlusFacets, getClassToReturn().getName(), getJustActive());
        } else {
            List<String> ids = new ArrayList<>();

            for (T item : selected) {
                ids.add(item.getUUID());
            }

            ret = new SelectedItemsList<>(ids, getClassToReturn().getName());
        }

        return ret;
    }

    public void setSelected(Set<T> newSelected) {
        selected.clear();
        selected.addAll(newSelected);
        redraw();
        fireOnCheckboxSelectionChanged();
    }

    public void clearSelected() {
        selected.clear();
        redraw();
        fireOnCheckboxSelectionChanged();
    }

    public int getIndexOfVisibleObject(T object) {
        int visibleIndex = getVisibleItems().indexOf(object);
        int visibleStartIndex = display.getVisibleRange().getStart();
        return visibleStartIndex + visibleIndex;
    }

    public ListSelectionState<T> getListSelectionState() {
        ListSelectionState<T> ret = null;
        T selectedObject = getSelectionModel().getSelectedObject();
        if (selectedObject != null) {
            int index = getIndexOfVisibleObject(selectedObject);
            ret = ListSelectionUtils.create(selectedObject, getFilter(), getJustActive(), getFacets(), getSorter(),
                    index);
        }
        return ret;
    }

    // LISTENER
    @FunctionalInterface
    public interface CheckboxSelectionListener<T extends IsIndexed> {
        public void onSelectionChange(SelectedItems<T> selected);
    }

    public void addCheckboxSelectionListener(CheckboxSelectionListener<T> checkboxSelectionListener) {
        listeners.add(checkboxSelectionListener);
    }

    public void removeCheckboxSelectionListener(CheckboxSelectionListener<T> listener) {
        listeners.remove(listener);
    }

    public void fireOnCheckboxSelectionChanged() {
        for (CheckboxSelectionListener<T> listener : listeners) {
            listener.onSelectionChange(getSelected());
        }
    }

    // SELECT ALL PANEL

    public void createSelectAllPanel() {
        selectAllPanel = new FlowPanel();
        selectAllPanelBody = new FlowPanel();
        selectAllCheckBox = new CheckBox();
        selectAllLabel = new Label("Select all");

        selectAllPanelBody.add(selectAllCheckBox);
        selectAllPanelBody.add(selectAllLabel);
        selectAllPanel.add(selectAllPanelBody);
        selectAllPanel.setVisible(false);

        selectAllPanel.addStyleName("panel");
        selectAllPanelBody.addStyleName("panel-body");

        selectAllCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {

            @Override
            public void onValueChange(ValueChangeEvent<Boolean> event) {
                fireOnCheckboxSelectionChanged();
            }
        });

    }

    public void showSelectAllPanel() {
        if (!selectAllPanel.isVisible() && resultsPager.hasNextPage() || resultsPager.hasPreviousPage()) {
            selectAllLabel.setText(messages.listSelectAllMessage(dataProvider.getRowCount()));
            selectAllCheckBox.setValue(false);
            selectAllPanel.setVisible(true);
        }
    }

    public void hideSelectAllPanel() {
        selectAllCheckBox.setValue(false);
        selectAllPanel.setVisible(false);
    }

    public Boolean isAllSelected() {
        return selectAllCheckBox.getValue();
    }

    public O getObject() {
        return object;
    }

    public int getRowCount() {
        return dataProvider.getRowCount();
    }

    public Date getDate() {
        return dataProvider.getDate();
    }

    public List<CheckboxSelectionListener<T>> getListeners() {
        return this.listeners;
    }

    protected void addColumn(Column<T, ?> column, SafeHtml headerHTML, boolean nowrap, boolean alignRight) {
        SafeHtmlHeader header = new SafeHtmlHeader(headerHTML);
        display.addColumn(column, header);

        if (nowrap && alignRight) {
            header.setHeaderStyleNames("nowrap text-align-right");
            column.setCellStyleNames("nowrap text-align-right");
        } else if (nowrap) {
            header.setHeaderStyleNames("cellTableFadeOut");
            column.setCellStyleNames("cellTableFadeOut");
        }
    }

    protected void addColumn(Column<T, ?> column, SafeHtml headerHTML, boolean nowrap, boolean alignRight,
            double fixedSize) {
        addColumn(column, headerHTML, nowrap, alignRight);
        display.setColumnWidth(column, fixedSize, Unit.EM);
    }

    protected void addColumn(Column<T, ?> column, String headerText, boolean nowrap, boolean alignRight) {
        addColumn(column, SafeHtmlUtils.fromString(headerText), nowrap, alignRight);
    }

    protected void addColumn(Column<T, ?> column, String headerText, boolean nowrap, boolean alignRight,
            double fixedSize) {
        addColumn(column, SafeHtmlUtils.fromString(headerText), nowrap, alignRight, fixedSize);
    }

    public IndexResult<T> getResult() {
        return result;
    }

    public void setResult(IndexResult<T> result) {
        this.result = result;
    }

    public String translate(String fieldName, String fieldValue) {
        String translation = null;
        if (this.result != null && this.result.getFacetResults() != null) {
            for (FacetFieldResult ffr : this.result.getFacetResults()) {
                if (ffr.getField().equalsIgnoreCase(fieldName)) {
                    if (ffr.getValues() != null) {
                        for (FacetValue fv : ffr.getValues()) {
                            if (fv.getValue().equalsIgnoreCase(fieldValue)) {
                                translation = fv.getLabel();
                                break;
                            }
                        }
                    }
                }
                if (translation != null) {
                    break;
                }
            }
        }
        if (translation == null) {
            translation = fieldValue;
        }
        return translation;
    }

    public boolean hasElementsSelected() {
        SelectedItems<T> selected = getSelected();

        if (selected instanceof SelectedItemsList) {
            SelectedItemsList<T> list = (SelectedItemsList<T>) selected;
            return !list.getIds().isEmpty();
        }

        return true;
    }

    public Actionable<T> getActionable() {
        return actionable;
    }

    public void setActionable(Actionable<T> actionable) {
        this.actionable = actionable;
        actionsButton.setVisible(actionable != null);
    }

    protected void showActions() {
        if (actionable != null) {
            if (actionsPopup.isShowing()) {
                actionsPopup.hide();
            } else {
                AsyncCallback<Actionable.ActionImpact> callback = new AsyncCallback<Actionable.ActionImpact>() {

                    @Override
                    public void onFailure(Throwable caught) {
                        AsyncCallbackUtils.defaultFailureTreatment(caught);
                    }

                    @Override
                    public void onSuccess(Actionable.ActionImpact impact) {
                        if (Actionable.ActionImpact.DESTROYED.equals(impact)) {
                            Timer timer = new Timer() {
                                @Override
                                public void run() {
                                    update();
                                }
                            };

                            timer.schedule(RodaConstants.ACTION_TIMEOUT);
                        } else if (!Actionable.ActionImpact.NONE.equals(impact)) {
                            update();
                        }
                        actionsPopup.hide();
                    }
                };

                if (isAllSelected()) {
                    actionsPopup.setWidget(actionable.createActionsLayout(getSelected(), callback));
                } else if (selected.size() == 1) {
                    actionsPopup.setWidget(actionable.createActionsLayout(selected.iterator().next(), callback));
                } else if (selected.size() > 1) {
                    // TODO create action layout based on selected set
                    actionsPopup.setWidget(actionable.createActionsLayout(getSelected(), callback));
                } else {
                    Label emptyHelpText = new Label(messages.tableActionEmptyHelp());
                    emptyHelpText.addStyleName("actions-empty-help");
                    actionsPopup.setWidget(emptyHelpText);
                }

                actionsPopup.showRelativeTo(actionsButton, CalloutPosition.BOTTOM_RIGHT);
            }
        }
    }

}