import org.primefaces.component.column.Column;
import org.primefaces.component.columns.Columns;
import org.primefaces.component.columngroup.ColumnGroup;
import org.primefaces.component.rowexpansion.RowExpansion;
import org.primefaces.component.row.Row;
import org.primefaces.component.subtable.SubTable;
import org.primefaces.component.contextmenu.ContextMenu;
import org.primefaces.component.summaryrow.SummaryRow;
import org.primefaces.context.RequestContext;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.logging.Logger;
import javax.faces.component.UIComponent;
import javax.faces.application.NavigationHandler;
import java.util.Map;
import java.util.Iterator;
import java.util.HashMap;
import org.primefaces.model.LazyDataModel;
import java.lang.StringBuilder;
import java.util.List;
import javax.el.ValueExpression;
import javax.faces.event.FacesEvent;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.PhaseId;
import org.primefaces.util.Constants;
import org.primefaces.event.RowEditEvent;
import org.primefaces.event.CellEditEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.primefaces.event.data.PageEvent;
import org.primefaces.event.data.SortEvent;
import org.primefaces.event.data.FilterEvent;
import org.primefaces.event.ColumnResizeEvent;
import org.primefaces.event.ToggleEvent;
import org.primefaces.event.ToggleSelectEvent;
import org.primefaces.event.ReorderEvent;
import org.primefaces.model.Visibility;
import org.primefaces.model.SortOrder;
import org.primefaces.model.SelectableDataModel;
import org.primefaces.model.SelectableDataModelWrapper;
import java.lang.reflect.Array;
import javax.el.ELContext;
import javax.el.MethodExpression;
import javax.faces.model.DataModel;
import javax.faces.FacesException;
import javax.faces.component.UINamingContainer;
import org.primefaces.component.api.UIColumn;
import org.primefaces.component.api.DynamicColumn;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.PostRestoreStateEvent;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.model.SortMeta;
import org.primefaces.component.datatable.feature.*;
import org.primefaces.util.ComponentUtils;
import org.primefaces.util.SharedStringBuilder;
private final static Logger logger = Logger.getLogger(DataTable.class.getName());
private static final String SB_GET_SELECTED_ROW_KEYS_AS_STRING = DataTable.class.getName() + "#getSelectedRowKeysAsString";
public static final String CONTAINER_CLASS = "ui-datatable ui-widget";
public static final String TABLE_WRAPPER_CLASS = "ui-datatable-tablewrapper";
public static final String RTL_CLASS = "ui-datatable-rtl";
public static final String COLUMN_HEADER_CLASS = "ui-state-default";
public static final String DYNAMIC_COLUMN_HEADER_CLASS = "ui-dynamic-column";
public static final String COLUMN_HEADER_CONTAINER_CLASS = "ui-header-column";
public static final String COLUMN_FOOTER_CLASS = "ui-state-default";
public static final String COLUMN_FOOTER_CONTAINER_CLASS = "ui-footer-column";
public static final String DATA_CLASS = "ui-datatable-data ui-widget-content";
public static final String ROW_CLASS = "ui-widget-content";
public static final String SELECTABLE_ROW_CLASS = "ui-datatable-selectable";
public static final String EMPTY_MESSAGE_ROW_CLASS = "ui-widget-content ui-datatable-empty-message";
public static final String HEADER_CLASS = "ui-datatable-header ui-widget-header ui-corner-top";
public static final String FOOTER_CLASS = "ui-datatable-footer ui-widget-header ui-corner-bottom";
public static final String SORTABLE_COLUMN_CLASS = "ui-sortable-column";
public static final String SORTABLE_COLUMN_ICON_CLASS = "ui-sortable-column-icon ui-icon ui-icon-carat-2-n-s";
public static final String SORTABLE_COLUMN_ASCENDING_ICON_CLASS = "ui-sortable-column-icon ui-icon ui-icon ui-icon-carat-2-n-s ui-icon-triangle-1-n";
public static final String SORTABLE_COLUMN_DESCENDING_ICON_CLASS = "ui-sortable-column-icon ui-icon ui-icon ui-icon-carat-2-n-s ui-icon-triangle-1-s";
public static final String STATIC_COLUMN_CLASS = "ui-static-column";
public static final String FILTER_COLUMN_CLASS = "ui-filter-column";
public static final String COLUMN_TITLE_CLASS = "ui-column-title";
public static final String COLUMN_FILTER_CLASS = "ui-column-filter ui-widget ui-state-default ui-corner-left";
public static final String COLUMN_INPUT_FILTER_CLASS = "ui-column-filter ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all";
public static final String COLUMN_CUSTOM_FILTER_CLASS = "ui-column-customfilter";
public static final String RESIZABLE_COLUMN_CLASS = "ui-resizable-column";
public static final String EXPANDED_ROW_CLASS = "ui-expanded-row";
public static final String EXPANDED_ROW_CONTENT_CLASS = "ui-expanded-row-content";
public static final String ROW_TOGGLER_CLASS = "ui-row-toggler";
public static final String EDITABLE_COLUMN_CLASS = "ui-editable-column";
public static final String CELL_EDITOR_CLASS = "ui-cell-editor";
public static final String CELL_EDITOR_INPUT_CLASS = "ui-cell-editor-input";
public static final String CELL_EDITOR_OUTPUT_CLASS = "ui-cell-editor-output";
public static final String ROW_EDITOR_COLUMN_CLASS = "ui-row-editor-column";
public static final String ROW_EDITOR_CLASS = "ui-row-editor ui-helper-clearfix";
public static final String SELECTION_COLUMN_CLASS = "ui-selection-column";
public static final String EVEN_ROW_CLASS = "ui-datatable-even";
public static final String ODD_ROW_CLASS = "ui-datatable-odd";
public static final String SCROLLABLE_CONTAINER_CLASS = "ui-datatable-scrollable";
public static final String SCROLLABLE_HEADER_CLASS = "ui-widget-header ui-datatable-scrollable-header";
public static final String SCROLLABLE_HEADER_BOX_CLASS = "ui-datatable-scrollable-header-box";
public static final String SCROLLABLE_BODY_CLASS = "ui-datatable-scrollable-body";
public static final String SCROLLABLE_FOOTER_CLASS = "ui-widget-header ui-datatable-scrollable-footer";
public static final String SCROLLABLE_FOOTER_BOX_CLASS = "ui-datatable-scrollable-footer-box";
public static final String COLUMN_RESIZER_CLASS = "ui-column-resizer";
public static final String RESIZABLE_CONTAINER_CLASS = "ui-datatable-resizable";
public static final String SUBTABLE_HEADER = "ui-datatable-subtable-header";
public static final String SUBTABLE_FOOTER = "ui-datatable-subtable-footer";
public static final String SUMMARY_ROW_CLASS = "ui-datatable-summaryrow ui-widget-header";
public static final String EDITING_ROW_CLASS = "ui-row-editing";
public static final String STICKY_HEADER_CLASS = "ui-datatable-sticky";
public static final String MOBILE_TABLE_CLASS = "ui-responsive ui-table ui-table-reflow table-stripe";
public static final String MOBILE_COLUMN_HEADER_CLASS = "ui-column-header";
public static final String MOBILE_ROW_CLASS = "ui-table-row";
private static final Collection<String> EVENT_NAMES = Collections.unmodifiableCollection(Arrays.asList("page","sort","filter", "rowSelect",
"rowUnselect", "rowEdit", "rowEditInit", "rowEditCancel", "colResize", "toggleSelect", "colReorder", "contextMenu"
,"rowSelectRadio", "rowSelectCheckbox", "rowUnselectCheckbox", "rowDblselect", "rowToggle"
,"cellEdit", "rowReorder"));
static Map<DataTableFeatureKey,DataTableFeature> FEATURES;
static {
FEATURES = new HashMap<DataTableFeatureKey,DataTableFeature>();
FEATURES.put(DataTableFeatureKey.DRAGGABLE_COLUMNS, new DraggableColumnsFeature());
FEATURES.put(DataTableFeatureKey.FILTER, new FilterFeature());
FEATURES.put(DataTableFeatureKey.PAGE, new PageFeature());
FEATURES.put(DataTableFeatureKey.SORT, new SortFeature());
FEATURES.put(DataTableFeatureKey.RESIZABLE_COLUMNS, new ResizableColumnsFeature());
FEATURES.put(DataTableFeatureKey.SELECT, new SelectionFeature());
FEATURES.put(DataTableFeatureKey.ROW_EDIT, new RowEditFeature());
FEATURES.put(DataTableFeatureKey.CELL_EDIT, new CellEditFeature());
FEATURES.put(DataTableFeatureKey.ROW_EXPAND, new RowExpandFeature());
FEATURES.put(DataTableFeatureKey.SCROLL, new ScrollFeature());
FEATURES.put(DataTableFeatureKey.DRAGGABLE_ROWS, new DraggableRowsFeature());
}
public DataTableFeature getFeature(DataTableFeatureKey key) {
return FEATURES.get(key);
}
public boolean shouldEncodeFeature(FacesContext context) {
return context.getExternalContext().getRequestParameterMap().containsKey(this.getClientId(context) + "_encodeFeature");
}
public boolean isRowEditRequest(FacesContext context) {
return context.getExternalContext().getRequestParameterMap().containsKey(this.getClientId(context) + "_rowEditAction");
}
public boolean isRowEditCancelRequest(FacesContext context) {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String value = params.get(this.getClientId(context) + "_rowEditAction");
return value != null && value.equals("cancel");
}
public boolean isRowSelectionEnabled() {
return this.getSelectionMode() != null;
}
public boolean isColumnSelectionEnabled() {
return getColumnSelectionMode() != null;
}
public String getColumnSelectionMode() {
for(UIComponent child : getChildren()) {
if(child.isRendered() && (child instanceof Column)) {
String selectionMode = ((Column) child).getSelectionMode();
if(selectionMode != null) {
return selectionMode;
}
}
}
return null;
}
public boolean isSelectionEnabled() {
return this.isRowSelectionEnabled() || isColumnSelectionEnabled();
}
public boolean isSingleSelectionMode() {
String selectionMode = this.getSelectionMode();
String columnSelectionMode = this.getColumnSelectionMode();
if(selectionMode != null)
return selectionMode.equalsIgnoreCase("single");
else if(columnSelectionMode != null)
return columnSelectionMode.equalsIgnoreCase("single");
else
return false;
}
@Override
public void processValidators(FacesContext context) {
super.processValidators(context);
if(this.isFilterRequest(context)) {
FEATURES.get(DataTableFeatureKey.FILTER).decode(context, this);
}
}
@Override
public void processUpdates(FacesContext context) {
super.processUpdates(context);
ValueExpression selectionVE = this.getValueExpression("selection");
if(selectionVE != null) {
selectionVE.setValue(context.getELContext(), this.getLocalSelection());
this.setSelection(null);
}
}
@Override
public void queueEvent(FacesEvent event) {
FacesContext context = getFacesContext();
if(isRequestSource(context) && event instanceof AjaxBehaviorEvent) {
setRowIndex(-1);
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String eventName = params.get(Constants.RequestParams.PARTIAL_BEHAVIOR_EVENT_PARAM);
String clientId = this.getClientId(context);
FacesEvent wrapperEvent = null;
AjaxBehaviorEvent behaviorEvent = (AjaxBehaviorEvent) event;
if(eventName.equals("rowSelect")||eventName.equals("rowSelectRadio")||eventName.equals("contextMenu")
||eventName.equals("rowSelectCheckbox")||eventName.equals("rowDblselect")) {
String rowKey = params.get(clientId + "_instantSelectedRowKey");
wrapperEvent = new SelectEvent(this, behaviorEvent.getBehavior(), this.getRowData(rowKey));
}
else if(eventName.equals("rowUnselect")||eventName.equals("rowUnselectCheckbox")) {
String rowKey = params.get(clientId + "_instantUnselectedRowKey");
wrapperEvent = new UnselectEvent(this, behaviorEvent.getBehavior(), this.getRowData(rowKey));
}
else if(eventName.equals("page")) {
int rows = this.getRowsToRender();
int first = Integer.parseInt(params.get(clientId + "_first"));
int page = rows > 0 ? (int) (first / rows) : 0;
wrapperEvent = new PageEvent(this, behaviorEvent.getBehavior(), page);
}
else if(eventName.equals("sort")) {
SortOrder order;
UIColumn sortColumn;
if(isMultiSort()) {
String[] sortDirs = params.get(clientId + "_sortDir").split(",");
String[] sortKeys = params.get(clientId + "_sortKey").split(",");
order = SortOrder.valueOf(((SortFeature) FEATURES.get(DataTableFeatureKey.SORT)).convertSortOrderParam(sortDirs[sortDirs.length - 1]));
sortColumn = findColumn(sortKeys[sortKeys.length - 1]);
}
else {
order = SortOrder.valueOf(((SortFeature) FEATURES.get(DataTableFeatureKey.SORT)).convertSortOrderParam(params.get(clientId + "_sortDir")));
sortColumn = findColumn(params.get(clientId + "_sortKey"));
}
wrapperEvent = new SortEvent(this, behaviorEvent.getBehavior(), sortColumn, order);
}
else if(eventName.equals("filter")) {
wrapperEvent = new FilterEvent(this, behaviorEvent.getBehavior(), getFilteredValue());
}
else if(eventName.equals("rowEdit")||eventName.equals("rowEditCancel")||eventName.equals("rowEditInit")) {
int rowIndex = Integer.parseInt(params.get(clientId + "_rowEditIndex"));
setRowIndex(rowIndex);
wrapperEvent = new RowEditEvent(this, behaviorEvent.getBehavior(), this.getRowData());
}
else if(eventName.equals("colResize")) {
String columnId = params.get(clientId + "_columnId");
int width = Double.valueOf(params.get(clientId + "_width")).intValue();
int height = Double.valueOf(params.get(clientId + "_height")).intValue();;
wrapperEvent = new ColumnResizeEvent(this, behaviorEvent.getBehavior(), width, height, findColumn(columnId));
}
else if(eventName.equals("toggleSelect")) {
boolean checked = Boolean.valueOf(params.get(clientId + "_checked"));
wrapperEvent = new ToggleSelectEvent(this, behaviorEvent.getBehavior(), checked);
}
else if(eventName.equals("colReorder")) {
wrapperEvent = behaviorEvent;
}
else if(eventName.equals("rowToggle")) {
boolean expansion = params.containsKey(clientId + "_rowExpansion");
Visibility visibility = expansion ? Visibility.VISIBLE : Visibility.HIDDEN;
String rowIndex = expansion ? params.get(clientId + "_expandedRowIndex") : params.get(clientId + "_collapsedRowIndex");
setRowIndex(Integer.parseInt(rowIndex));
wrapperEvent = new ToggleEvent(this, behaviorEvent.getBehavior(), visibility, getRowData());
}
else if(eventName.equals("cellEdit")) {
String[] cellInfo = params.get(clientId + "_cellInfo").split(",");
int rowIndex = Integer.parseInt(cellInfo[0]);
int cellIndex = Integer.parseInt(cellInfo[1]);
int i = -1;
UIColumn column = null;
for(UIColumn col : this.getColumns()) {
if(col.isRendered()) {
i++;
if(i == cellIndex) {
column = col;
break;
}
}
}
wrapperEvent = new CellEditEvent(this, behaviorEvent.getBehavior(), rowIndex, column);
}
else if(eventName.equals("rowReorder")) {
int fromIndex = Integer.parseInt(params.get(clientId + "_fromIndex"));
int toIndex = Integer.parseInt(params.get(clientId + "_toIndex"));
wrapperEvent = new ReorderEvent(this, behaviorEvent.getBehavior(), fromIndex, toIndex);
}
wrapperEvent.setPhaseId(event.getPhaseId());
super.queueEvent(wrapperEvent);
}
else {
super.queueEvent(event);
}
}
public UIColumn findColumn(String clientId) {
for(UIColumn column : this.getColumns()) {
if(column.getColumnKey().equals(clientId)) {
return column;
}
}
FacesContext context = this.getFacesContext();
ColumnGroup headerGroup = this.getColumnGroup("header");
for(UIComponent row : headerGroup.getChildren()) {
for(UIComponent col : row.getChildren()) {
if(col.getClientId(context).equals(clientId)) {
return (UIColumn) col;
}
}
}
throw new FacesException("Cannot find column with key: " + clientId);
}
public ColumnGroup getColumnGroup(String target) {
for(UIComponent child : this.getChildren()) {
if(child instanceof ColumnGroup) {
ColumnGroup colGroup = (ColumnGroup) child;
String type = colGroup.getType();
if(type != null && type.equals(target)) {
return colGroup;
}
}
}
return null;
}
public boolean hasFooterColumn() {
for(UIComponent child : getChildren()) {
if(child.isRendered() && (child instanceof UIColumn)) {
UIColumn column = (UIColumn) child;
if(column.getFacet("footer") != null || column.getFooterText() != null)
return true;
}
}
return false;
}
public void loadLazyData() {
DataModel model = getDataModel();
if(model != null && model instanceof LazyDataModel) {
LazyDataModel lazyModel = (LazyDataModel) model;
List<?> data = null;
// #7176
calculateFirst();
if(this.isMultiSort()) {
data = lazyModel.load(getFirst(), getRows(), getMultiSortMeta(), getFilters());
}
else {
data = lazyModel.load(getFirst(), getRows(), resolveSortField(), convertSortOrder(), getFilters());
}
lazyModel.setPageSize(getRows());
lazyModel.setWrappedData(data);
//Update paginator for callback
if(this.isPaginator()) {
RequestContext requestContext = RequestContext.getCurrentInstance();
if(requestContext != null) {
requestContext.addCallbackParam("totalRecords", lazyModel.getRowCount());
}
}
}
}
public void loadLazyScrollData(int offset, int rows) {
DataModel model = getDataModel();
if(model != null && model instanceof LazyDataModel) {
LazyDataModel lazyModel = (LazyDataModel) model;
List<?> data = null;
if(this.isMultiSort()) {
data = lazyModel.load(offset, rows, getMultiSortMeta(), getFilters());
}
else {
data = lazyModel.load(offset, rows, resolveSortField(), convertSortOrder(), getFilters());
}
lazyModel.setPageSize(rows);
lazyModel.setWrappedData(data);
//Update paginator for callback
if(this.isPaginator()) {
RequestContext requestContext = RequestContext.getCurrentInstance();
if(requestContext != null) {
requestContext.addCallbackParam("totalRecords", lazyModel.getRowCount());
}
}
}
}
protected String resolveSortField() {
String sortField = null;
UIColumn column = this.getSortColumn();
ValueExpression tableSortByVE = this.getValueExpression("sortBy");
Object tableSortByProperty = this.getSortBy();
if(column == null) {
String field = this.getSortField();
if(field == null)
sortField = (tableSortByVE == null) ? (String) tableSortByProperty : resolveStaticField(tableSortByVE);
else
sortField = field;
}
else {
ValueExpression columnSortByVE = column.getValueExpression("sortBy");
if(column.isDynamic()) {
((DynamicColumn) sortColumn).applyStatelessModel();
Object sortByProperty = sortColumn.getSortBy();
String field = column.getField();
if(field == null)
sortField = (sortByProperty == null) ? resolveDynamicField(columnSortByVE) : sortByProperty.toString();
else
sortField = field;
}
else {
String field = column.getField();
if(field == null)
sortField = (columnSortByVE == null) ? (String) column.getSortBy() : resolveStaticField(columnSortByVE);
else
sortField = field;
}
}
return sortField;
}
public SortOrder convertSortOrder() {
String sortOrder = getSortOrder();
if(sortOrder == null)
return SortOrder.UNSORTED;
else
return SortOrder.valueOf(sortOrder.toUpperCase(Locale.ENGLISH));
}
public String resolveStaticField(ValueExpression expression) {
if(expression != null) {
String expressionString = expression.getExpressionString();
expressionString = expressionString.substring(2, expressionString.length() - 1); //Remove #{}
return expressionString.substring(expressionString.indexOf(".") + 1); //Remove var
}
else {
return null;
}
}
public String resolveDynamicField(ValueExpression expression) {
if(expression != null) {
String expressionString = expression.getExpressionString();
expressionString = expressionString.substring(expressionString.indexOf("[") + 1, expressionString.indexOf("]"));
expressionString = "#{" + expressionString + "}";
FacesContext context = getFacesContext();
ELContext eLContext = context.getELContext();
ValueExpression dynaVE = context.getApplication()
.getExpressionFactory().createValueExpression(eLContext, expressionString, String.class);
return (String) dynaVE.getValue(eLContext);
}
else {
return null;
}
}
public void clearLazyCache() {
LazyDataModel model = (LazyDataModel) getDataModel();
model.setWrappedData(null);
}
public Map<String,Object> getFilters() {
return (Map<String,Object>) getStateHelper().eval("filters", new HashMap<String,Object>());
}
public void setFilters(Map<String,Object> filters) {
getStateHelper().put("filters", filters);
}
public int getScrollOffset() {
return (java.lang.Integer) getStateHelper().eval("scrollOffset", 0);
}
public void setScrollOffset(int scrollOffset) {
getStateHelper().put("scrollOffset", scrollOffset);
}
private List filterMetadata;
public List getFilterMetadata() {
return filterMetadata;
}
public void setFilterMetadata(List filterMetadata) {
this.filterMetadata = filterMetadata;
}
private boolean reset = false;
public boolean isReset() {
return reset;
}
public void resetValue() {
setValue(null);
setFilteredValue(null);
setFilters(null);
}
public void reset() {
resetValue();
setFirst(0);
this.reset = true;
this.setValueExpression("sortBy", this.getDefaultSortByVE());
this.setSortFunction(this.getDefaultSortFunction());
this.setSortOrder(this.getDefaultSortOrder());
this.setSortByVE(null);
this.setSortColumn(null);
this.setSortField(null);
this.clearMultiSortMeta();
}
public boolean isFilteringEnabled() {
Object value = getStateHelper().get("filtering");
return value == null ? false : true;
}
public void enableFiltering() {
getStateHelper().put("filtering", true);
}
public RowExpansion getRowExpansion() {
for(UIComponent kid : getChildren()) {
if(kid instanceof RowExpansion)
return (RowExpansion) kid;
}
return null;
}
public Object getLocalSelection() {
return getStateHelper().get(PropertyKeys.selection);
}
@Override
public Collection<String> getEventNames() {
return EVENT_NAMES;
}
public boolean isRequestSource(FacesContext context) {
String partialSource = context.getExternalContext().getRequestParameterMap().get(Constants.RequestParams.PARTIAL_SOURCE_PARAM);
return partialSource != null && this.getClientId(context).equals(partialSource);
}
public boolean isBodyUpdate(FacesContext context) {
String clientId = this.getClientId(context);
return context.getExternalContext().getRequestParameterMap().containsKey(clientId + "_updateBody");
}
public SubTable getSubTable() {
for(UIComponent kid : getChildren()) {
if(kid instanceof SubTable)
return (SubTable) kid;
}
return null;
}
public Object getRowKeyFromModel(Object object) {
DataModel model = getDataModel();
if(!(model instanceof SelectableDataModel)) {
throw new FacesException("DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.");
}
return ((SelectableDataModel) getDataModel()).getRowKey(object);
}
public Object getRowData(String rowKey) {
boolean hasRowKeyVe = this.getValueExpression("rowKey") != null;
if(hasRowKeyVe) {
Map<String,Object> requestMap = getFacesContext().getExternalContext().getRequestMap();
String var = this.getVar();
Collection data = (Collection) getDataModel().getWrappedData();
for(Iterator it = data.iterator(); it.hasNext();) {
Object object = it.next();
requestMap.put(var, object);
if(String.valueOf(this.getRowKey()).equals(rowKey)) {
return object;
}
}
return null;
}
else {
DataModel model = getDataModel();
if(!(model instanceof SelectableDataModel)) {
throw new FacesException("DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled or you need to define rowKey attribute");
}
return ((SelectableDataModel) getDataModel()).getRowData(rowKey);
}
}
private List<Object> selectedRowKeys = new ArrayList<Object>();
public void findSelectedRowKeys() {
Object selection = this.getSelection();
selectedRowKeys = new ArrayList<Object>();
boolean hasRowKeyVe = this.getValueExpression("rowKey") != null;
String var = this.getVar();
Map<String,Object> requestMap = getFacesContext().getExternalContext().getRequestMap();
if(isSelectionEnabled() && selection != null) {
if(this.isSingleSelectionMode()) {
addToSelectedRowKeys(selection, requestMap, var, hasRowKeyVe);
}
else {
if(selection.getClass().isArray()) {
for(int i = 0; i < Array.getLength(selection); i++) {
addToSelectedRowKeys(Array.get(selection, i), requestMap, var, hasRowKeyVe);
}
}
else {
List<?> list = (List<?>) selection;
for(Iterator<? extends Object> it = list.iterator(); it.hasNext();) {
addToSelectedRowKeys(it.next(), requestMap, var, hasRowKeyVe);
}
}
}
}
}
protected void addToSelectedRowKeys(Object object, Map<String,Object> map, String var, boolean hasRowKey) {
if(hasRowKey) {
map.put(var, object);
Object rowKey = this.getRowKey();
if (rowKey != null) {
this.selectedRowKeys.add(rowKey);
}
}
else {
Object rowKey = this.getRowKeyFromModel(object);
if (rowKey != null) {
this.selectedRowKeys.add(rowKey);
}
}
}
public List<Object> getSelectedRowKeys() {
return selectedRowKeys;
}
public String getSelectedRowKeysAsString() {
StringBuilder builder = SharedStringBuilder.get(SB_GET_SELECTED_ROW_KEYS_AS_STRING);
for(Iterator<Object> iter = getSelectedRowKeys().iterator(); iter.hasNext();) {
builder.append(iter.next());
if(iter.hasNext()) {
builder.append(",");
}
}
return builder.toString();
}
public SummaryRow getSummaryRow() {
for(UIComponent kid : getChildren()) {
if(kid.isRendered() && kid instanceof SummaryRow) {
return (SummaryRow) kid;
}
}
return null;
}
private int columnsCount = -1;
public int getColumnsCount() {
if(columnsCount == -1) {
columnsCount = 0;
for(UIComponent kid : getChildren()) {
if(kid.isRendered()) {
if(kid instanceof Columns) {
int dynamicColumnsCount = ((Columns) kid).getRowCount();
if(dynamicColumnsCount > 0) {
columnsCount += dynamicColumnsCount;
}
}
else if(kid instanceof Column) {
columnsCount++;
}
else if(kid instanceof SubTable) {
SubTable subTable = (SubTable) kid;
for(UIComponent subTableKid : subTable.getChildren()) {
if(subTableKid.isRendered() && subTableKid instanceof Column) {
columnsCount++;
}
}
}
}
}
}
return columnsCount;
}
private List<UIColumn> columns;
public List<UIColumn> getColumns() {
if(columns == null) {
columns = new ArrayList<UIColumn>();
FacesContext context = getFacesContext();
char separator = UINamingContainer.getSeparatorChar(context);
for(UIComponent child : this.getChildren()) {
if(child instanceof Column) {
columns.add((UIColumn) child);
}
else if(child instanceof Columns) {
Columns uiColumns = (Columns) child;
String uiColumnsClientId = uiColumns.getClientId(context);
for(int i=0; i < uiColumns.getRowCount(); i++) {
DynamicColumn dynaColumn = new DynamicColumn(i, uiColumns);
dynaColumn.setColumnKey(uiColumnsClientId + separator + i);
columns.add(dynaColumn);
}
}
}
}
return columns;
}
public void setColumns(List<UIColumn> columns) {
this.columns = columns;
}
public String getScrollState() {
Map<String,String> params = getFacesContext().getExternalContext().getRequestParameterMap();
String name = this.getClientId() + "_scrollState";
String value = params.get(name);
return value == null ? "0,0" : value;
}
@Override
protected boolean shouldSkipChildren(FacesContext context) {
return this.isSkipChildren() || context.getExternalContext().getRequestParameterMap().containsKey(this.getClientId(context) + "_skipChildren");
}
private UIColumn sortColumn;
public void setSortColumn(UIColumn column) {
this.sortColumn = column;
if(column == null)
getStateHelper().remove("sortColumnKey");
else
getStateHelper().put("sortColumnKey", column.getColumnKey());
}
public UIColumn getSortColumn() {
if(sortColumn == null) {
String sortColumnKey = (String) getStateHelper().get("sortColumnKey");
if(sortColumnKey != null) {
sortColumn = this.findColumn(sortColumnKey);
}
}
return sortColumn;
}
public boolean isMultiSort() {
String sortMode = this.getSortMode();
return (sortMode != null && sortMode.equals("multiple"));
}
private List<SortMeta> multiSortMeta = null;
public List<SortMeta> getMultiSortMeta() {
if(multiSortMeta != null) {
return multiSortMeta;
}
List<MultiSortState> multiSortStateList = (List<MultiSortState>) this.getStateHelper().get("multiSortState");
if(multiSortStateList != null && !multiSortStateList.isEmpty()) {
multiSortMeta = new ArrayList<SortMeta>();
for(int i = 0; i < multiSortStateList.size(); i++) {
MultiSortState multiSortState = multiSortStateList.get(i);
SortMeta sortMeta = new SortMeta();
sortMeta.setSortBy(this.findColumn(multiSortState.getSortKey()));
sortMeta.setSortField(multiSortState.getSortField());
sortMeta.setSortOrder(multiSortState.getSortOrder());
sortMeta.setSortFunction(multiSortState.getSortFunction());
multiSortMeta.add(sortMeta);
}
}
else {
ValueExpression ve = this.getValueExpression("sortBy");
if(ve != null) {
multiSortMeta = (List<SortMeta>) ve.getValue(getFacesContext().getELContext());
}
}
return multiSortMeta;
}
public void setMultiSortMeta(List<SortMeta> value) {
this.multiSortMeta = value;
if(value != null && !value.isEmpty()) {
List<MultiSortState> multiSortStateList = new ArrayList<MultiSortState>();
for(int i = 0; i < value.size(); i++) {
multiSortStateList.add(new MultiSortState(value.get(i)));
}
this.getStateHelper().put("multiSortState", multiSortStateList);
}
}
private void clearMultiSortMeta() {
this.multiSortMeta = null;
this.getStateHelper().remove("multiSortState");
}
public boolean isRTL() {
return this.getDir().equalsIgnoreCase("rtl");
}
public String resolveSelectionMode() {
String tableSelectionMode = this.getSelectionMode();
String columnSelectionMode = this.getColumnSelectionMode();
String selectionMode = null;
if(tableSelectionMode != null)
selectionMode = tableSelectionMode;
else if(columnSelectionMode != null)
selectionMode = columnSelectionMode.equals("single") ? "radio" : "checkbox";
return selectionMode;
}
@Override
protected boolean requiresColumns() {
return true;
}
private Columns dynamicColumns;
public void setDynamicColumns(Columns value) {
this.dynamicColumns = value;
}
public Columns getDynamicColumns() {
return dynamicColumns;
}
@Override
protected void processColumnFacets(FacesContext context, PhaseId phaseId) {
if(getChildCount() > 0) {
for(UIComponent child : this.getChildren()) {
if(child.isRendered()) {
if(child instanceof UIColumn) {
if(child instanceof Column) {
for(UIComponent facet : child.getFacets().values()) {
process(context, facet, phaseId);
}
}
else if(child instanceof Columns) {
Columns uicolumns = (Columns) child;
int f = uicolumns.getFirst();
int r = uicolumns.getRows();
int l = (r == 0) ? uicolumns.getRowCount() : (f + r);
for(int i = f; i < l; i++) {
uicolumns.setRowIndex(i);
if(!uicolumns.isRowAvailable()) {
break;
}
for(UIComponent facet : child.getFacets().values()) {
process(context, facet, phaseId);
}
}
uicolumns.setRowIndex(-1);
}
}
else if(child instanceof ColumnGroup) {
if(child.getChildCount() > 0) {
for(UIComponent columnGroupChild : child.getChildren()) {
if(columnGroupChild instanceof Row && columnGroupChild.getChildCount() > 0) {
for(UIComponent rowChild : columnGroupChild.getChildren()) {
if(rowChild instanceof Column && rowChild.getFacetCount() > 0) {
for(UIComponent facet : rowChild.getFacets().values()) {
process(context, facet, phaseId);
}
}
else {
process(context, rowChild, phaseId); //e.g ui:repeat
}
}
}
else {
process(context, columnGroupChild, phaseId); //e.g ui:repeat
}
}
}
}
}
}
}
}
private ValueExpression sortByVE;
public void setSortByVE(ValueExpression ve) {
this.sortByVE = ve;
}
public ValueExpression getSortByVE() {
return this.sortByVE;
}
public void setDefaultSortByVE(ValueExpression ve) {
this.setValueExpression("defaultSortBy", ve);
}
public ValueExpression getDefaultSortByVE() {
return this.getValueExpression("defaultSortBy");
}
public void setDefaultSortOrder(String val) {
this.getStateHelper().put("defaultSortOrder", val);
}
public String getDefaultSortOrder() {
return (String) this.getStateHelper().get("defaultSortOrder");
}
public void setDefaultSortFunction(MethodExpression obj) {
this.getStateHelper().put("defaultSortFunction", obj);
}
public MethodExpression getDefaultSortFunction() {
return (MethodExpression) this.getStateHelper().get("defaultSortFunction");
}
public Locale resolveDataLocale() {
FacesContext context = this.getFacesContext();
Object userLocale = this.getDataLocale();
if(userLocale != null) {
if(userLocale instanceof String)
return ComponentUtils.toLocale((String) userLocale);
else if(userLocale instanceof java.util.Locale)
return (java.util.Locale) userLocale;
else
throw new IllegalArgumentException("Type:" + userLocale.getClass() + " is not a valid locale type for datatable:" + this.getClientId(context));
}
else {
return context.getViewRoot().getLocale();
}
}
private boolean isFilterRequest(FacesContext context) {
return context.getExternalContext().getRequestParameterMap().containsKey(this.getClientId(context) + "_filtering");
}
private List<UIComponent> iterableChildren;
@Override
protected List<UIComponent> getIterableChildren() {
if(iterableChildren == null) {
iterableChildren = new ArrayList<UIComponent>();
for(UIComponent child : this.getChildren()) {
if(!(child instanceof ColumnGroup)) {
iterableChildren.add(child);
}
}
}
return iterableChildren;
}
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
super.processEvent(event);
if(!this.isLazy() && event instanceof PostRestoreStateEvent && (this == event.getComponent())) {
Object filteredValue = this.getFilteredValue();
if(filteredValue != null) {
this.updateValue(filteredValue);
}
}
}
public void updateFilteredValue(FacesContext context, List<?> value) {
ValueExpression ve = this.getValueExpression("filteredValue");
if(ve != null) {
ve.setValue(context.getELContext(), value);
}
else {
this.setFilteredValue(value);
}
}
public void updateValue(Object value) {
Object originalValue = this.getValue();
if(originalValue instanceof SelectableDataModel)
this.setValue(new SelectableDataModelWrapper((SelectableDataModel) originalValue, value));
else
this.setValue(value);
}
@Override
public Object saveState(FacesContext context) {
if(this.isFilteringEnabled()) {
this.setValue(null);
}
return super.saveState(context);
}