org.primefaces.component.api.UIData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of primefaces Show documentation
Show all versions of primefaces Show documentation
PrimeFaces is one of the most popular UI libraries in Java EE Ecosystem and widely used by software companies, world renowned brands, banks, financial institutions, insurance companies, universities and more.
/**
* The MIT License
*
* Copyright (c) 2009-2019 PrimeTek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.primefaces.component.api;
import java.io.IOException;
import java.sql.ResultSet;
import java.util.*;
import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.application.StateManager;
import javax.faces.component.*;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import javax.faces.event.PostValidateEvent;
import javax.faces.event.PreRenderComponentEvent;
import javax.faces.event.PreValidateEvent;
import javax.faces.model.*;
import javax.faces.render.Renderer;
import org.primefaces.component.column.Column;
import org.primefaces.component.columngroup.ColumnGroup;
import org.primefaces.component.columns.Columns;
import org.primefaces.component.inputtext.InputText;
import org.primefaces.model.CollectionDataModel;
import org.primefaces.model.IterableDataModel;
import org.primefaces.util.ComponentTraversalUtils;
import org.primefaces.util.SharedStringBuilder;
public class UIData extends javax.faces.component.UIData {
public static final String PAGINATOR_TOP_CONTAINER_CLASS = "ui-paginator ui-paginator-top ui-widget-header";
public static final String PAGINATOR_BOTTOM_CONTAINER_CLASS = "ui-paginator ui-paginator-bottom ui-widget-header";
public static final String PAGINATOR_PAGES_CLASS = "ui-paginator-pages";
public static final String PAGINATOR_TOP_LEFT_CONTENT_CLASS = "ui-paginator-top-left-content";
public static final String PAGINATOR_TOP_RIGHT_CONTENT_CLASS = "ui-paginator-top-right-content";
public static final String PAGINATOR_BOTTOM_LEFT_CONTENT_CLASS = "ui-paginator-bottom-left-content";
public static final String PAGINATOR_BOTTOM_RIGHT_CONTENT_CLASS = "ui-paginator-bottom-right-content";
public static final String PAGINATOR_PAGE_CLASS = "ui-paginator-page ui-state-default ui-corner-all";
public static final String PAGINATOR_ACTIVE_PAGE_CLASS = "ui-paginator-page ui-state-default ui-state-active ui-corner-all";
public static final String PAGINATOR_CURRENT_CLASS = "ui-paginator-current";
public static final String PAGINATOR_RPP_OPTIONS_CLASS = "ui-paginator-rpp-options ui-widget ui-state-default ui-corner-left";
public static final String PAGINATOR_RPP_LABEL_CLASS = "ui-paginator-rpp-label ui-helper-hidden";
public static final String PAGINATOR_JTP_SELECT_CLASS = "ui-paginator-jtp-select ui-widget ui-state-default ui-corner-left";
public static final String PAGINATOR_JTP_INPUT_CLASS = "ui-paginator-jtp-input " + InputText.STYLE_CLASS;
public static final String PAGINATOR_FIRST_PAGE_LINK_CLASS = "ui-paginator-first ui-state-default ui-corner-all";
public static final String PAGINATOR_FIRST_PAGE_ICON_CLASS = "ui-icon ui-icon-seek-first";
public static final String PAGINATOR_PREV_PAGE_LINK_CLASS = "ui-paginator-prev ui-state-default ui-corner-all";
public static final String PAGINATOR_PREV_PAGE_ICON_CLASS = "ui-icon ui-icon-seek-prev";
public static final String PAGINATOR_NEXT_PAGE_LINK_CLASS = "ui-paginator-next ui-state-default ui-corner-all";
public static final String PAGINATOR_NEXT_PAGE_ICON_CLASS = "ui-icon ui-icon-seek-next";
public static final String PAGINATOR_LAST_PAGE_LINK_CLASS = "ui-paginator-last ui-state-default ui-corner-all";
public static final String PAGINATOR_LAST_PAGE_ICON_CLASS = "ui-icon ui-icon-seek-end";
public static final String ARIA_HEADER_LABEL = "primefaces.paginator.aria.HEADER";
public static final String ARIA_FIRST_PAGE_LABEL = "primefaces.paginator.aria.FIRST_PAGE";
public static final String ARIA_PREVIOUS_PAGE_LABEL = "primefaces.paginator.aria.PREVIOUS_PAGE";
public static final String ARIA_NEXT_PAGE_LABEL = "primefaces.paginator.aria.NEXT_PAGE";
public static final String ARIA_LAST_PAGE_LABEL = "primefaces.paginator.aria.LAST_PAGE";
public static final String ROWS_PER_PAGE_LABEL = "primefaces.paginator.aria.ROWS_PER_PAGE";
private static final String SB_ID = UIData.class.getName() + "#id";
private final Map _rowTransientStates = new HashMap<>();
private String clientId = null;
private DataModel model = null;
private Object oldVar = null;
private Map _rowDeltaStates = new HashMap<>();
private Object _initialDescendantFullComponentState = null;
private Boolean isNested = null;
public enum PropertyKeys {
paginator,
paginatorTemplate,
rowsPerPageTemplate,
rowsPerPageLabel,
currentPageReportTemplate,
pageLinks,
paginatorPosition,
paginatorAlwaysVisible,
rowIndex,
rowIndexVar,
saved,
lazy,
rowStatePreserved;
}
public boolean isPaginator() {
return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.paginator, false);
}
public void setPaginator(boolean _paginator) {
getStateHelper().put(PropertyKeys.paginator, _paginator);
}
public java.lang.String getPaginatorTemplate() {
return (java.lang.String) getStateHelper().eval(PropertyKeys.paginatorTemplate,
"{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}");
}
public void setPaginatorTemplate(java.lang.String _paginatorTemplate) {
getStateHelper().put(PropertyKeys.paginatorTemplate, _paginatorTemplate);
}
public java.lang.String getRowsPerPageTemplate() {
return (java.lang.String) getStateHelper().eval(PropertyKeys.rowsPerPageTemplate, null);
}
public void setRowsPerPageTemplate(java.lang.String _rowsPerPageTemplate) {
getStateHelper().put(PropertyKeys.rowsPerPageTemplate, _rowsPerPageTemplate);
}
public java.lang.String getRowsPerPageLabel() {
return (java.lang.String) getStateHelper().eval(PropertyKeys.rowsPerPageLabel, null);
}
public void setRowsPerPageLabel(java.lang.String _rowsPerPageLabel) {
getStateHelper().put(PropertyKeys.rowsPerPageLabel, _rowsPerPageLabel);
}
public java.lang.String getCurrentPageReportTemplate() {
return (java.lang.String) getStateHelper().eval(PropertyKeys.currentPageReportTemplate, "({currentPage} of {totalPages})");
}
public void setCurrentPageReportTemplate(java.lang.String _currentPageReportTemplate) {
getStateHelper().put(PropertyKeys.currentPageReportTemplate, _currentPageReportTemplate);
}
public int getPageLinks() {
return (java.lang.Integer) getStateHelper().eval(PropertyKeys.pageLinks, 10);
}
public void setPageLinks(int _pageLinks) {
getStateHelper().put(PropertyKeys.pageLinks, _pageLinks);
}
public java.lang.String getPaginatorPosition() {
return (java.lang.String) getStateHelper().eval(PropertyKeys.paginatorPosition, "both");
}
public void setPaginatorPosition(java.lang.String _paginatorPosition) {
getStateHelper().put(PropertyKeys.paginatorPosition, _paginatorPosition);
}
public boolean isPaginatorAlwaysVisible() {
return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.paginatorAlwaysVisible, true);
}
public void setPaginatorAlwaysVisible(boolean _paginatorAlwaysVisible) {
getStateHelper().put(PropertyKeys.paginatorAlwaysVisible, _paginatorAlwaysVisible);
}
public boolean isLazy() {
return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.lazy, false);
}
public void setLazy(boolean _lazy) {
getStateHelper().put(PropertyKeys.lazy, _lazy);
}
public java.lang.String getRowIndexVar() {
return (java.lang.String) getStateHelper().eval(PropertyKeys.rowIndexVar, null);
}
public void setRowIndexVar(java.lang.String _rowIndexVar) {
getStateHelper().put(PropertyKeys.rowIndexVar, _rowIndexVar);
}
@Override
public boolean isRowStatePreserved() {
return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.rowStatePreserved, false);
}
@Override
public void setRowStatePreserved(boolean _paginator) {
getStateHelper().put(PropertyKeys.rowStatePreserved, _paginator);
}
public void calculateFirst() {
int rows = getRows();
if (rows > 0) {
int first = getFirst();
int rowCount = getRowCount();
if (rowCount > 0 && first >= rowCount) {
int numberOfPages = (int) Math.ceil(rowCount * 1d / rows);
setFirst(Math.max((numberOfPages - 1) * rows, 0));
}
}
}
public int getPage() {
if (getRowCount() > 0) {
int rows = getRowsToRender();
if (rows > 0) {
int first = getFirst();
return first / rows;
}
else {
return 0;
}
}
else {
return 0;
}
}
public int getPageCount() {
return (int) Math.ceil(getRowCount() * 1d / getRowsToRender());
}
public int getRowsToRender() {
int rows = getRows();
return rows == 0 ? getRowCount() : rows;
}
public boolean isPaginationRequest(FacesContext context) {
return context.getExternalContext().getRequestParameterMap().containsKey(getClientId(context) + "_pagination");
}
private boolean isRowsPerPageValid(UIData data, String rowsParam) {
if (rowsParam == null) {
return true;
}
String rowsPerPageTemplate = data.getRowsPerPageTemplate();
if (rowsPerPageTemplate != null) {
String[] options = rowsPerPageTemplate.split("[,]+");
for (String option : options) {
String opt = option.trim();
if (opt.equals(rowsParam) || (opt.startsWith("{ShowAll|") && Integer.toString(getRowCount()).equals(rowsParam))) {
return true;
}
}
return false;
}
int rows = data.getRows();
if (rows > 0) {
return Integer.toString(rows).equals(rowsParam);
}
return true;
}
public void updatePaginationData(FacesContext context, UIData data) {
data.setRowIndex(-1);
String componentClientId = data.getClientId(context);
Map params = context.getExternalContext().getRequestParameterMap();
ELContext elContext = context.getELContext();
String firstParam = params.get(componentClientId + "_first");
String rowsParam = params.get(componentClientId + "_rows");
if (!isRowsPerPageValid(data, rowsParam)) {
throw new IllegalArgumentException("Unsupported rows per page value: " + rowsParam);
}
data.setFirst(Integer.valueOf(firstParam));
data.setRows(Integer.valueOf(rowsParam));
ValueExpression firstVe = data.getValueExpression("first");
ValueExpression rowsVe = data.getValueExpression("rows");
if (firstVe != null && !firstVe.isReadOnly(elContext)) {
firstVe.setValue(context.getELContext(), data.getFirst());
}
if (rowsVe != null && !rowsVe.isReadOnly(elContext)) {
rowsVe.setValue(context.getELContext(), data.getRows());
}
}
@Override
public void processDecodes(FacesContext context) {
if (!isRendered()) {
return;
}
pushComponentToEL(context, this);
preDecode(context);
processPhase(context, PhaseId.APPLY_REQUEST_VALUES);
decode(context);
popComponentFromEL(context);
}
@Override
public void processValidators(FacesContext context) {
if (!isRendered()) {
return;
}
pushComponentToEL(context, this);
Application app = context.getApplication();
app.publishEvent(context, PreValidateEvent.class, this);
preValidate(context);
processPhase(context, PhaseId.PROCESS_VALIDATIONS);
app.publishEvent(context, PostValidateEvent.class, this);
popComponentFromEL(context);
}
@Override
public void processUpdates(FacesContext context) {
if (!isRendered()) {
return;
}
pushComponentToEL(context, this);
preUpdate(context);
processPhase(context, PhaseId.UPDATE_MODEL_VALUES);
popComponentFromEL(context);
}
protected void processPhase(FacesContext context, PhaseId phaseId) {
if (shouldSkipChildren(context)) {
return;
}
setRowIndex(-1);
processFacets(context, phaseId);
if (requiresColumns()) {
processColumnFacets(context, phaseId);
}
processChildren(context, phaseId);
setRowIndex(-1);
}
protected void processFacets(FacesContext context, PhaseId phaseId) {
if (getFacetCount() > 0) {
for (UIComponent facet : getFacets().values()) {
process(context, facet, phaseId);
}
}
}
protected void processColumnFacets(FacesContext context, PhaseId phaseId) {
for (UIComponent child : getChildren()) {
if (child.isRendered() && (child.getFacetCount() > 0)) {
for (UIComponent facet : child.getFacets().values()) {
process(context, facet, phaseId);
}
}
}
}
protected void processChildren(FacesContext context, PhaseId phaseId) {
int first = getFirst();
int rows = getRows();
int last = rows == 0 ? getRowCount() : (first + rows);
for (int rowIndex = first; rowIndex < last; rowIndex++) {
setRowIndex(rowIndex);
if (!isRowAvailable()) {
break;
}
for (UIComponent child : getIterableChildren()) {
if (child.isRendered()) {
if (child instanceof Column) {
for (UIComponent grandkid : child.getChildren()) {
process(context, grandkid, phaseId);
}
}
else {
process(context, child, phaseId);
}
}
}
}
}
protected void process(FacesContext context, UIComponent component, PhaseId phaseId) {
if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
component.processDecodes(context);
}
else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
component.processValidators(context);
}
else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
component.processUpdates(context);
}
}
@Override
public String getClientId(FacesContext context) {
if (clientId != null) {
return clientId;
}
String id = getId();
if (id == null) {
UniqueIdVendor parentUniqueIdVendor = ComponentTraversalUtils.closestUniqueIdVendor(this);
if (parentUniqueIdVendor == null) {
UIViewRoot viewRoot = context.getViewRoot();
if (viewRoot != null) {
id = viewRoot.createUniqueId();
}
else {
throw new FacesException("Cannot create clientId for " + getClass().getCanonicalName());
}
}
else {
id = parentUniqueIdVendor.createUniqueId(context, null);
}
setId(id);
}
UIComponent namingContainer = ComponentTraversalUtils.closestNamingContainer(this);
if (namingContainer != null) {
String containerClientId = namingContainer.getContainerClientId(context);
if (containerClientId != null) {
StringBuilder sb = SharedStringBuilder.get(getFacesContext(), SB_ID, containerClientId.length() + 10);
clientId = sb.append(containerClientId).append(UINamingContainer.getSeparatorChar(context)).append(id).toString();
}
else {
clientId = id;
}
}
else {
clientId = id;
}
Renderer renderer = getRenderer(context);
if (renderer != null) {
clientId = renderer.convertClientId(context, clientId);
}
return clientId;
}
@Override
public String getContainerClientId(FacesContext context) {
//clientId is without rowIndex
String componentClientId = getClientId(context);
int rowIndex = getRowIndex();
if (rowIndex == -1) {
return componentClientId;
}
StringBuilder sb = SharedStringBuilder.get(getFacesContext(), SB_ID, componentClientId.length() + 4);
String containerClientId = sb.append(componentClientId).append(UINamingContainer.getSeparatorChar(context)).append(rowIndex).toString();
return containerClientId;
}
@Override
public void setId(String id) {
super.setId(id);
//clear
clientId = null;
}
//Row State preserved implementation is taken from Mojarra
private void setRowIndexRowStatePreserved(int rowIndex) {
if (rowIndex < -1) {
throw new IllegalArgumentException("rowIndex is less than -1");
}
if (getRowIndex() == rowIndex) {
return;
}
FacesContext facesContext = getFacesContext();
if (_initialDescendantFullComponentState != null) {
//Just save the row
Map sm = saveFullDescendantComponentStates(facesContext, null, getChildren().iterator(), false);
if (sm != null && !sm.isEmpty()) {
_rowDeltaStates.put(getContainerClientId(facesContext), sm);
}
if (getRowIndex() != -1) {
_rowTransientStates.put(getContainerClientId(facesContext),
saveTransientDescendantComponentStates(facesContext, null, getChildren().iterator(), false));
}
}
// Update to the new row index
//this.rowIndex = rowIndex;
getStateHelper().put(PropertyKeys.rowIndex, rowIndex);
DataModel localModel = getDataModel();
localModel.setRowIndex(rowIndex);
// if rowIndex is -1, clear the cache
if (rowIndex == -1) {
setDataModel(null);
}
// Clear or expose the current row data as a request scope attribute
String var = getVar();
if (var != null) {
Map requestMap
= getFacesContext().getExternalContext().getRequestMap();
if (rowIndex == -1) {
oldVar = requestMap.remove(var);
}
else if (isRowAvailable()) {
requestMap.put(var, getRowData());
}
else {
requestMap.remove(var);
if (null != oldVar) {
requestMap.put(var, oldVar);
oldVar = null;
}
}
}
if (_initialDescendantFullComponentState != null) {
Object rowState = _rowDeltaStates.get(getContainerClientId(facesContext));
if (rowState == null) {
//Restore as original
restoreFullDescendantComponentStates(facesContext, getChildren().iterator(), _initialDescendantFullComponentState, false);
}
else {
//Restore first original and then delta
restoreFullDescendantComponentDeltaStates(facesContext, getChildren().iterator(), rowState, _initialDescendantFullComponentState, false);
}
if (getRowIndex() == -1) {
restoreTransientDescendantComponentStates(facesContext, getChildren().iterator(), null, false);
}
else {
rowState = _rowTransientStates.get(getContainerClientId(facesContext));
if (rowState == null) {
restoreTransientDescendantComponentStates(facesContext, getChildren().iterator(), null, false);
}
else {
restoreTransientDescendantComponentStates(facesContext, getChildren().iterator(), (Map) rowState, false);
}
}
}
}
private void setRowIndexWithoutRowStatePreserved(int rowIndex) {
saveDescendantState();
setRowModel(rowIndex);
restoreDescendantState();
}
public void setRowModel(int rowIndex) {
//update rowIndex
getStateHelper().put(PropertyKeys.rowIndex, rowIndex);
getDataModel().setRowIndex(rowIndex);
//clear datamodel
if (rowIndex == -1) {
setDataModel(null);
}
//update var
String var = getVar();
if (var != null) {
String rowIndexVar = getRowIndexVar();
Map requestMap = getFacesContext().getExternalContext().getRequestMap();
if (rowIndex == -1) {
oldVar = requestMap.remove(var);
if (rowIndexVar != null) {
requestMap.remove(rowIndexVar);
}
}
else if (isRowAvailable()) {
requestMap.put(var, getRowData());
if (rowIndexVar != null) {
requestMap.put(rowIndexVar, rowIndex);
}
}
else {
requestMap.remove(var);
if (rowIndexVar != null) {
requestMap.put(rowIndexVar, rowIndex);
}
if (oldVar != null) {
requestMap.put(var, oldVar);
oldVar = null;
}
}
}
}
@Override
public int getRowIndex() {
return (Integer) getStateHelper().eval(PropertyKeys.rowIndex, -1);
}
@Override
public void setRowIndex(int rowIndex) {
if (isRowStatePreserved()) {
setRowIndexRowStatePreserved(rowIndex);
}
else {
setRowIndexWithoutRowStatePreserved(rowIndex);
}
}
protected void saveDescendantState() {
FacesContext context = getFacesContext();
if (getChildCount() > 0) {
for (UIComponent kid : getChildren()) {
saveDescendantState(kid, context);
}
}
if (getFacetCount() > 0) {
for (UIComponent facet : getFacets().values()) {
saveDescendantState(facet, context);
}
}
}
protected void saveDescendantState(UIComponent component, FacesContext context) {
Map saved = (Map) getStateHelper().get(PropertyKeys.saved);
if (component instanceof EditableValueHolder) {
EditableValueHolder input = (EditableValueHolder) component;
SavedState state = null;
String componentClientId = component.getClientId(context);
if (saved == null) {
state = new SavedState();
getStateHelper().put(PropertyKeys.saved, componentClientId, state);
}
if (state == null) {
state = saved.get(componentClientId);
if (state == null) {
state = new SavedState();
getStateHelper().put(PropertyKeys.saved, componentClientId, state);
}
}
state.setValue(input.getLocalValue());
state.setValid(input.isValid());
state.setSubmittedValue(input.getSubmittedValue());
state.setLocalValueSet(input.isLocalValueSet());
}
else if (component instanceof UIForm) {
UIForm form = (UIForm) component;
String componentClientId = component.getClientId(context);
SavedState state = null;
if (saved == null) {
state = new SavedState();
getStateHelper().put(PropertyKeys.saved, componentClientId, state);
}
if (state == null) {
state = saved.get(componentClientId);
if (state == null) {
state = new SavedState();
//saved.put(clientId, state);
getStateHelper().put(PropertyKeys.saved, componentClientId, state);
}
}
state.setSubmitted(form.isSubmitted());
}
//save state for children
if (component.getChildCount() > 0) {
for (UIComponent kid : component.getChildren()) {
saveDescendantState(kid, context);
}
}
//save state for facets
if (component.getFacetCount() > 0) {
for (UIComponent facet : component.getFacets().values()) {
saveDescendantState(facet, context);
}
}
}
protected void restoreDescendantState() {
FacesContext context = getFacesContext();
if (getChildCount() > 0) {
for (UIComponent kid : getChildren()) {
restoreDescendantState(kid, context);
}
}
if (getFacetCount() > 0) {
for (UIComponent facet : getFacets().values()) {
restoreDescendantState(facet, context);
}
}
}
protected void restoreDescendantState(UIComponent component, FacesContext context) {
String id = component.getId();
component.setId(id); //reset the client id
Map saved = (Map) getStateHelper().get(PropertyKeys.saved);
if (component instanceof EditableValueHolder) {
EditableValueHolder input = (EditableValueHolder) component;
String componentClientId = component.getClientId(context);
SavedState state = saved.get(componentClientId);
if (state == null) {
state = new SavedState();
}
input.setValue(state.getValue());
input.setValid(state.isValid());
input.setSubmittedValue(state.getSubmittedValue());
input.setLocalValueSet(state.isLocalValueSet());
}
else if (component instanceof UIForm) {
UIForm form = (UIForm) component;
String componentClientId = component.getClientId(context);
SavedState state = saved.get(componentClientId);
if (state == null) {
state = new SavedState();
}
form.setSubmitted(state.getSubmitted());
state.setSubmitted(form.isSubmitted());
}
//restore state of children
if (component.getChildCount() > 0) {
for (UIComponent kid : component.getChildren()) {
restoreDescendantState(kid, context);
}
}
//restore state of facets
if (component.getFacetCount() > 0) {
for (UIComponent facet : component.getFacets().values()) {
restoreDescendantState(facet, context);
}
}
}
@Override
protected DataModel getDataModel() {
if (model != null) {
return (model);
}
Object current = getValue();
if (current == null) {
setDataModel(new ListDataModel(Collections.emptyList()));
}
else if (current instanceof DataModel) {
setDataModel((DataModel) current);
}
else if (current instanceof List) {
setDataModel(new ListDataModel((List) current));
}
else if (Object[].class.isAssignableFrom(current.getClass())) {
setDataModel(new ArrayDataModel((Object[]) current));
}
else if (current instanceof ResultSet) {
setDataModel(new ResultSetDataModel((ResultSet) current));
}
else if (current instanceof Collection) {
setDataModel(new CollectionDataModel((Collection) current));
}
else if (current instanceof Iterable) {
setDataModel(new IterableDataModel((Iterable) current));
}
else if (current instanceof Map) {
setDataModel(new IterableDataModel(((Map) current).entrySet()));
}
else {
setDataModel(new ScalarDataModel(current));
}
return model;
}
@Override
protected void setDataModel(DataModel dataModel) {
model = dataModel;
}
protected boolean shouldSkipChildren(FacesContext context) {
return false;
}
protected boolean shouldVisitChildren(VisitContext context, boolean visitRows) {
if (visitRows) {
setRowIndex(-1);
}
Collection idsToVisit = context.getSubtreeIdsToVisit(this);
return (!idsToVisit.isEmpty());
}
@Override
public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
throws FacesException {
String baseClientId = getClientId(context);
// skip if the component is not a children of the UIData
if (!clientId.startsWith(baseClientId)) {
return false;
}
return super.invokeOnComponent(context, clientId, callback);
}
@Override
public boolean visitTree(VisitContext context, VisitCallback callback) {
if (!isVisitable(context)) {
return false;
}
FacesContext facesContext = context.getFacesContext();
boolean visitRows = shouldVisitRows(facesContext, context);
int rowIndex = -1;
if (visitRows) {
rowIndex = getRowIndex();
setRowIndex(-1);
}
pushComponentToEL(facesContext, null);
try {
VisitResult result = context.invokeVisitCallback(this, callback);
if (result == VisitResult.COMPLETE) {
return true;
}
if ((result == VisitResult.ACCEPT) && shouldVisitChildren(context, visitRows)) {
if (visitFacets(context, callback, visitRows)) {
return true;
}
if (requiresColumns() && visitColumnsAndColumnFacets(context, callback, visitRows)) {
return true;
}
if (visitRows(context, callback, visitRows)) {
return true;
}
}
}
finally {
popComponentFromEL(facesContext);
if (visitRows) {
setRowIndex(rowIndex);
}
}
return false;
}
protected boolean visitFacets(VisitContext context, VisitCallback callback, boolean visitRows) {
if (visitRows) {
setRowIndex(-1);
}
if (getFacetCount() > 0) {
for (UIComponent facet : getFacets().values()) {
if (facet.visitTree(context, callback)) {
return true;
}
}
}
return false;
}
protected boolean visitColumnsAndColumnFacets(VisitContext context, VisitCallback callback, boolean visitRows) {
if (visitRows) {
setRowIndex(-1);
}
if (getChildCount() > 0) {
for (UIComponent child : getChildren()) {
VisitResult result = context.invokeVisitCallback(child, callback); // visit the column directly
if (result == VisitResult.COMPLETE) {
return true;
}
if (child instanceof UIColumn) {
if (child.getFacetCount() > 0) {
if (child instanceof Columns) {
Columns columns = (Columns) child;
for (int i = 0; i < columns.getRowCount(); i++) {
columns.setRowIndex(i);
boolean value = visitColumnFacets(context, callback, child);
if (value) {
return true;
}
}
columns.setRowIndex(-1);
}
else {
boolean value = visitColumnFacets(context, callback, child);
if (value) {
return true;
}
}
}
}
else if (child instanceof ColumnGroup) {
visitColumnGroup(context, callback, (ColumnGroup) child);
}
}
}
return false;
}
protected boolean visitColumnGroup(VisitContext context, VisitCallback callback, ColumnGroup group) {
if (group.getChildCount() > 0) {
for (UIComponent row : group.getChildren()) {
if (row.getChildCount() > 0) {
for (UIComponent col : row.getChildren()) {
if (col instanceof Column && col.getFacetCount() > 0) {
boolean value = visitColumnFacets(context, callback, col);
if (value) {
return true;
}
}
}
}
}
}
return false;
}
protected boolean visitColumnFacets(VisitContext context, VisitCallback callback, UIComponent component) {
for (UIComponent columnFacet : component.getFacets().values()) {
if (columnFacet.visitTree(context, callback)) {
return true;
}
}
return false;
}
protected boolean visitRows(VisitContext context, VisitCallback callback, boolean visitRows) {
boolean requiresColumns = requiresColumns();
int processed = 0;
int rowIndex = 0;
int rows = 0;
if (visitRows) {
rowIndex = getFirst() - 1;
rows = getRows();
}
while (true) {
if (visitRows) {
if ((rows > 0) && (++processed > rows)) {
break;
}
setRowIndex(++rowIndex);
if (!isRowAvailable()) {
break;
}
}
if (getChildCount() > 0) {
for (UIComponent kid : getChildren()) {
if (requiresColumns) {
if (kid instanceof Columns) {
Columns uicolumns = (Columns) kid;
for (int i = 0; i < uicolumns.getRowCount(); i++) {
uicolumns.setRowIndex(i);
boolean value = visitColumnContent(context, callback, uicolumns);
if (value) {
uicolumns.setRowIndex(-1);
return true;
}
}
uicolumns.setRowIndex(-1);
}
else {
boolean value = visitColumnContent(context, callback, kid);
if (value) {
return true;
}
}
}
else {
if (kid.visitTree(context, callback)) {
return true;
}
}
}
}
if (!visitRows) {
break;
}
}
return false;
}
protected boolean visitColumnContent(VisitContext context, VisitCallback callback, UIComponent component) {
if (component.getChildCount() > 0) {
for (UIComponent grandkid : component.getChildren()) {
if (grandkid.visitTree(context, callback)) {
return true;
}
}
}
return false;
}
protected boolean shouldVisitRows(FacesContext context, VisitContext visitContext) {
try {
//JSF 2.1
VisitHint skipHint = VisitHint.valueOf("SKIP_ITERATION");
return !visitContext.getHints().contains(skipHint);
}
catch (IllegalArgumentException e) {
//JSF 2.0
Object skipHint = context.getAttributes().get("javax.faces.visit.SKIP_ITERATION");
return !Boolean.TRUE.equals(skipHint);
}
}
protected boolean requiresColumns() {
return false;
}
protected List getIterableChildren() {
return getChildren();
}
@Override
public void markInitialState() {
if (isRowStatePreserved()) {
if (getFacesContext().getAttributes().containsKey(StateManager.IS_BUILDING_INITIAL_STATE)) {
_initialDescendantFullComponentState = saveDescendantInitialComponentStates(getFacesContext(), getChildren().iterator(), false);
}
}
super.markInitialState();
}
private void restoreFullDescendantComponentStates(FacesContext facesContext,
Iterator childIterator, Object state,
boolean restoreChildFacets) {
Iterator descendantStateIterator = null;
while (childIterator.hasNext()) {
if (descendantStateIterator == null && state != null) {
descendantStateIterator = ((Collection) state)
.iterator();
}
UIComponent component = childIterator.next();
// reset the client id (see spec 3.1.6)
component.setId(component.getId());
if (!component.isTransient()) {
Object childState = null;
Object descendantState = null;
if (descendantStateIterator != null
&& descendantStateIterator.hasNext()) {
Object[] object = descendantStateIterator.next();
childState = object[0];
descendantState = object[1];
}
component.clearInitialState();
component.restoreState(facesContext, childState);
component.markInitialState();
Iterator childsIterator;
if (restoreChildFacets) {
childsIterator = component.getFacetsAndChildren();
}
else {
childsIterator = component.getChildren().iterator();
}
restoreFullDescendantComponentStates(facesContext, childsIterator,
descendantState, true);
}
}
}
private Collection