Java tutorial
/** * 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; } }