org.richfaces.component.UIExtendedDataTable.java Source code

Java tutorial

Introduction

Here is the source code for org.richfaces.component.UIExtendedDataTable.java

Source

/**
* License Agreement.
*
* JBoss RichFaces - Ajax4jsf Component Library
*
* Copyright (C) 2008 CompuGROUP Holding AG
* 
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    
*/

package org.richfaces.component;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;
import javax.faces.model.DataModel;

import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.context.ContextInitParameters;
import org.ajax4jsf.event.AjaxEvent;
import org.ajax4jsf.model.ExtendedDataModel;
import org.apache.commons.collections.iterators.IteratorChain;
import org.richfaces.event.extdt.ChangeColumnVisibilityEvent;
import org.richfaces.event.extdt.ColumnResizeEvent;
import org.richfaces.event.extdt.DragDropEvent;
import org.richfaces.event.extdt.ExtTableFilterEvent;
import org.richfaces.event.extdt.ExtTableSortEvent;
import org.richfaces.model.ExtendedTableDataModel;
import org.richfaces.model.ExtendedTableDataModifiableModel;
import org.richfaces.model.FilterField;
import org.richfaces.model.LocaleAware;
import org.richfaces.model.Modifiable;
import org.richfaces.model.ModifiableModel;
import org.richfaces.model.Ordering;
import org.richfaces.model.SortField2;

/**
 * JSF component class
 * 
 */
public abstract class UIExtendedDataTable extends UIDataTable implements Selectable, Filterable, Sortable2 {

    /**
     * COMPONENT_TYPE
     */
    public static final String COMPONENT_TYPE = "org.richfaces.ExtendedDataTable";

    /**
     * COMPONENT_FAMILY
     */
    public static final String COMPONENT_FAMILY = "org.richfaces.ExtendedDataTable";

    protected ExtendedDataTableState state;

    public abstract Object getActiveRowKey();

    public abstract void setActiveRowKey(Object activeRowKey);

    public abstract String getGroupingColumn();

    public abstract void setGroupingColumn(String groupingColumn);

    public abstract void setTableState(String tableState);

    public abstract String getTableState();

    public void broadcast(FacesEvent event) throws AbortProcessingException {
        super.broadcast(event);
        if (event instanceof AjaxEvent) {
            //TODO nick - add regions from component too
            AjaxContext.getCurrentInstance().addComponentToAjaxRender(this);
        } else if (event instanceof DragDropEvent) {
            processDradDrop((DragDropEvent) event);
        } else if (event instanceof ChangeColumnVisibilityEvent) {
            processChangeColumnVisibility((ChangeColumnVisibilityEvent) event);
        } else if (event instanceof ColumnResizeEvent) {
            processColumnResize((ColumnResizeEvent) event);
        } else if (event instanceof ExtTableSortEvent) {
            processSortingChange((ExtTableSortEvent) event);
        } else if (event instanceof ExtTableFilterEvent) {
            processFilteringChange((ExtTableFilterEvent) event);
        }

    }

    public void queueEvent(FacesEvent event) {
        if (event.getSource() instanceof UIExtendedDataTable) {
            if (event instanceof AjaxEvent) {
                event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
            } else if (event instanceof DragDropEvent) {
                new AjaxEvent(this).queue();
                event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
            } else if (event instanceof ChangeColumnVisibilityEvent) {
                new AjaxEvent(this).queue();
                event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
            } else if (event instanceof ColumnResizeEvent) {
                event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
            } else if (event instanceof ExtTableSortEvent) {
                new AjaxEvent(this).queue();
                event.setPhaseId(PhaseId.INVOKE_APPLICATION);
            } else if (event instanceof ExtTableFilterEvent) {
                new AjaxEvent(this).queue();
                event.setPhaseId(PhaseId.INVOKE_APPLICATION);
            }
        }
        super.queueEvent(event);
    }

    public Iterator<UIColumn> getSortedColumns() {
        return new SortedColumnsIterator(this);
    }

    public Iterator<UIColumn> getChildColumns() {
        return new ExtendedTableColumnsIterator(this);
    }

    public void processDradDrop(DragDropEvent event) {
        String dragValue = event.getDragValue().toString();// dnd_drag_script
        String dropValue = event.getDropValue().toString();// dnd_drop_script

        getState().changeColumnsOrder(dragValue, dropValue, event.isDropBefore());
        //getFacesContext().renderResponse();
    }

    public List<UIComponent> getSortedChildren() {
        return getState().sortColumns(getFacesContext(), super.getChildren());
    }

    public void processChangeColumnVisibility(ChangeColumnVisibilityEvent event) {
        getState().toggleColumnVisibility(this, event.getColumnId());
        //getFacesContext().renderResponse();
    }

    public void processSortingChange(ExtTableSortEvent event) {
        DataModel dataModel = getDataModel();
        if (dataModel instanceof ExtendedTableDataModifiableModel<?>) {
            ((ExtendedTableDataModifiableModel<?>) dataModel).resetSort();
        } else {
            super.resetDataModel();
        }
        getFacesContext().renderResponse();
    }

    public void processFilteringChange(ExtTableFilterEvent event) {
        DataModel dataModel = getDataModel();
        if (dataModel instanceof ExtendedTableDataModifiableModel<?>) {
            ((ExtendedTableDataModifiableModel<?>) dataModel).resetFilter();
        } else {
            super.resetDataModel();
        }
        resetGroupVisibilityState();
        getFacesContext().renderResponse();
    }

    public boolean isColumnVisible(UIComponent column) {
        return getState().isColumnVisible(column.getId());
    }

    public void processColumnResize(ColumnResizeEvent event) {
        getState().changeColumnSize(this, event.getColumnWidths());
        //getFacesContext().renderResponse();
    }

    public String getColumnSize(UIComponent column) {
        return getState().getColumnSize(column);
    }

    public boolean isGroupingOn() {
        //first get it from state
        String groupingColumnId = getGroupByColumnId();
        return ((groupingColumnId != null) && (!"".equals(groupingColumnId))
                && (!ExtendedDataTableState.NONE_COLUMN_ID.equals(groupingColumnId)));
    }

    /**
     * Get id of column which the data is grouped by. First tries to get it
     * from the table state. If the table state doesn't provide such
     * information, get from component attribute.
     * 
     * @return id of column which the data is grouped by
     */
    public String getGroupByColumnId() {
        String id = getState().getGroupingColumnId();
        if (id == null) {//grouping is not saved in state
            //get column id from attribute
            id = getGroupingColumn();
        }
        return id;
    }

    /**
     * Get column component which the data is grouped by. First tries to get it
     * from the table state. If the table state doesn't provide such
     * information, get from component attribute.
     * 
     * @return column which the data is grouped by
     */
    public UIColumn getGroupByColumn() {
        if (!isGroupingOn()) {
            return null;
        }
        String groupingColumnId = getGroupByColumnId();
        for (Iterator<UIColumn> columns = getChildColumns(); columns.hasNext();) {
            UIColumn child = columns.next();
            if (groupingColumnId.equalsIgnoreCase(child.getId())) {
                return child;
            }
        }
        return null;
    }

    public void setGroupByColumn(org.richfaces.component.UIColumn column) {
        if (column == null) {
            getState().disableGrouping();
        } else {
            getState().groupBy(column.getId(), column.getSortOrder());
        }
    }

    protected void resetGroupVisibilityState() {
        getState().resetGroupVisibilityState();
    }

    public void disableGrouping() {
        getState().disableGrouping();
    }

    public boolean groupIsExpanded(int index) {
        return getState().groupIsExpanded(index);
    }

    public void toggleGroup(int index) {
        getState().toggleGroup(index);
    }

    protected Collection<Object> getGroupPriority() {
        Collection<Object> priority = getSortPriority();
        if (isGroupingOn()) {// grouping is on
            UIColumn column = getGroupByColumn();
            if ((column.getSortOrder() == null) || (column.getSortOrder().equals(Ordering.UNSORTED))) {
                column.setSortOrder(Ordering.ASCENDING);
            }
            String groupColId = column.getId();
            // try to add group column id as first
            if (priority.contains(groupColId)) {
                priority.remove(groupColId);
            }
            if (priority instanceof List) {
                ((List<Object>) priority).add(0, groupColId);
            } else {
                priority.add(groupColId);
            }
        }
        return priority;
    }

    //   public Object saveState(FacesContext context) {
    //      Object values[] = new Object[2];
    //      values[0] = super.saveState(context);
    //      values[1] = state;
    //      return values;
    //   }
    //
    //   public void restoreState(FacesContext context, Object state) {
    //      Object values[] = (Object[]) state;
    //      super.restoreState(context, values[0]);
    //      this.state = (ExtendedDataTableState) values[1];
    //   }

    public int getVisibleColumnsCount() {
        int count = 0;
        for (Iterator<UIColumn> iter = getChildColumns(); iter.hasNext();) {
            UIColumn column = iter.next();
            if (column.isRendered())
                count++;
        } // for
        return count;
    }// getVisibleColumnnCount

    @Override
    @SuppressWarnings("unchecked")
    protected ExtendedDataModel createDataModel() {
        List<FilterField> filterFields = new LinkedList<FilterField>();
        Map<String, SortField2> sortFieldsMap = new LinkedHashMap<String, SortField2>();
        Collection<Object> sortPriority = getGroupPriority();
        List<UIComponent> list = getChildren();
        for (Iterator<UIComponent> iterator = list.iterator(); iterator.hasNext();) {
            UIComponent component = iterator.next();
            if (component instanceof UIColumn) {
                UIColumn column = (UIColumn) component;
                FilterField filterField = column.getFilterField();
                if (filterField != null) {
                    filterFields.add(filterField);
                }
                SortField2 sortField = column.getSortField();
                if (sortField != null) {
                    sortFieldsMap.put(component.getId(), sortField);
                }
            }

        }
        List<SortField2> sortFields = new LinkedList<SortField2>();

        if (sortPriority != null) {
            for (Object object : sortPriority) {
                if (object instanceof String) {
                    String id = (String) object;
                    SortField2 sortField = sortFieldsMap.get(id);
                    if (sortField != null) {
                        sortFields.add(sortField);
                        sortFieldsMap.remove(id);
                    }
                }
            }
        }
        sortFields.addAll(sortFieldsMap.values());
        setFilterFields(filterFields);
        setSortFields(sortFields);

        ExtendedDataModel dataModel = (ExtendedDataModel) getDataModel();
        if (dataModel instanceof ExtendedTableDataModifiableModel<?>) {
            ((ExtendedTableDataModifiableModel<?>) dataModel).setVar(getVar());
        }
        if ((filterFields != null && !filterFields.isEmpty()) || (sortFields != null && !sortFields.isEmpty())) {
            Modifiable modifiable = null;
            if (dataModel instanceof Modifiable) {
                modifiable = (Modifiable) dataModel;
            } else if (dataModel instanceof ExtendedTableDataModel<?>) {
                ExtendedTableDataModel<?> tableDataModel = (ExtendedTableDataModel<?>) dataModel;
                //ExtendedTableDataModifiableModelOld<?> modifiableModel = new ExtendedTableDataModifiableModelOld(tableDataModel, getVar());
                ExtendedTableDataModifiableModel<?> modifiableModel = new ExtendedTableDataModifiableModel(
                        tableDataModel, getVar());
                dataModel = modifiableModel;
                modifiable = modifiableModel;
            } else {
                ModifiableModel modifiableModel = new ModifiableModel(dataModel, getVar());
                dataModel = modifiableModel;
                modifiable = modifiableModel;
            }

            if (dataModel instanceof LocaleAware) {
                FacesContext facesContext = getFacesContext();
                if (ContextInitParameters.isDatatableUsesViewLocale(facesContext)) {
                    UIViewRoot viewRoot = facesContext.getViewRoot();
                    ((LocaleAware) dataModel).setLocale(viewRoot.getLocale());
                }
            }

            modifiable.modify(filterFields, sortFields);
        }
        return dataModel;
    }

    /**
     * Original version of this method is defined in
     * {@link org.ajax4jsf.component.UIDataAdaptor} and is called before
     * RENDER_RESPONSE phase. In that version data model is reseted which causes
     * need to sort and filter every time component is rendered.
     */
    // @Override
    protected void resetDataModel() {
        // Do not reset only for ExtendedTableDataModel model
        if (!(getDataModel() instanceof ExtendedTableDataModel<?>)) {
            super.resetDataModel();
        }
    }

    @SuppressWarnings("unchecked")
    public Iterator<UIComponent> fixedChildren() {
        IteratorChain chain = new IteratorChain(getFacets().values().iterator());
        //RF-1248 Adding facets to both dataChildren and fixed children
        //To make both supports and header/footer work
        for (Iterator<UIComponent> i = getChildren().iterator(); i.hasNext();) {
            UIComponent kid = (UIComponent) i.next();
            if (kid instanceof Column || kid instanceof UIColumn) {
                chain.addIterator(kid.getFacets().values().iterator());
            }
        }

        return chain;
    }

    @Override
    public void beforeRenderResponse(FacesContext context) {
        super.beforeRenderResponse(context);

        for (Iterator<UIColumn> columns = getChildColumns(); columns.hasNext();) {
            UIColumn column = columns.next();
            column.setId(column.getId());
            column.setVisible(isColumnVisible(column));
        }

        UIColumn groupingColumn = getGroupByColumn();
        if (groupingColumn != null) {// grouping is on
            if (groupingColumn.getSortOrder().equals(Ordering.UNSORTED)) {
                groupingColumn.setSortOrder(Ordering.ASCENDING);
            }
        }
    }

    @Override
    public void processUpdates(FacesContext context) {
        super.processUpdates(context);
        updateTableState(context);
    }

    /**
     * Puts own state into component state. 
     */
    protected void updateTableState(FacesContext context) {
        ValueExpression ve = getValueExpression("tableState");
        if ((null != ve) && (!ve.isReadOnly(context.getELContext()))) {
            ve.setValue(context.getELContext(), getState().toString());
        }
    }//publishChanges

    protected ExtendedDataTableState getState() {
        if (state == null) {
            state = ExtendedDataTableState.getExtendedDataTableState(this);
        }
        return state;
    }

}