All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.primefaces.component.api.UITree Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 14.0.0-RC3
Show newest version
/**
 * Copyright 2009-2018 PrimeTek.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.primefaces.component.api;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
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.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PostValidateEvent;
import javax.faces.event.PreValidateEvent;

import org.primefaces.component.columns.Columns;
import org.primefaces.component.tree.UITreeNode;
import org.primefaces.model.TreeNode;
import org.primefaces.util.MessageFactory;
import org.primefaces.util.SharedStringBuilder;

public abstract class UITree extends UIComponentBase implements NamingContainer {

    private static final String SB_GET_CONTAINER_CLIENT_ID = UITree.class.getName() + "#getContainerClientId";
    private static final String SB_GET_SELECTED_ROW_KEYS_AS_STRING = UITree.class.getName() + "#getSelectedRowKeysAsString";

    public final static String SEPARATOR = "_";

    public final static String REQUIRED_MESSAGE_ID = "primefaces.tree.REQUIRED";

    public final static String CHECKBOX_CLASS = "ui-selection";

    private String rowKey;

    private TreeNode rowNode;

    private boolean rtl;

    private List preselection;

    public enum PropertyKeys {
        var
        ,selectionMode
        ,selection
        ,saved
        ,value
        ,required
        ,requiredMessage
        ,skipChildren
        ,showUnselectableCheckbox
        ,nodeVar;

        String toString;

        PropertyKeys(String toString) {
            this.toString = toString;
        }

        PropertyKeys() {
        }

        @Override
        public String toString() {
            return ((this.toString != null) ? this.toString : super.toString());
        }
    }

    public String getRowKey() {
        return rowKey;
    }

    public void setRowKey(String rowKey) {
        Map requestMap = getFacesContext().getExternalContext().getRequestMap();
        saveDescendantState();
        String nodeVar = this.getNodeVar();

        this.rowKey = rowKey;

        if (rowKey == null) {
            requestMap.remove(getVar());
            this.rowNode = null;
            if (nodeVar != null) {
                requestMap.remove(nodeVar);
            }
        }
        else {
            TreeNode root = getValue();
            this.rowNode = findTreeNode(root, rowKey);

            if (this.rowNode != null) {
                requestMap.put(getVar(), this.rowNode.getData());

                if (nodeVar != null) {
                    requestMap.put(nodeVar, this.rowNode);
                }
            }
            else {
                requestMap.remove(getVar());

                if (nodeVar != null) {
                    requestMap.remove(nodeVar);
                }
            }
        }

        restoreDescendantState();
    }

    private void addToPreselection(TreeNode node) {
        if (preselection == null) {
            preselection = new ArrayList();
        }

        preselection.add(node);
    }

    public TreeNode getRowNode() {
        return rowNode;
    }

    public java.lang.String getVar() {
        return (String) getStateHelper().eval(PropertyKeys.var, null);
    }

    public void setVar(java.lang.String _var) {
        getStateHelper().put(PropertyKeys.var, _var);
    }

    public java.lang.String getNodeVar() {
        return (String) getStateHelper().eval(PropertyKeys.nodeVar, null);
    }

    public void setNodeVar(java.lang.String _nodeVar) {
        getStateHelper().put(PropertyKeys.nodeVar, _nodeVar);
    }

    public TreeNode getValue() {
        return (TreeNode) getStateHelper().eval(PropertyKeys.value, null);
    }

    public void setValue(TreeNode _value) {
        getStateHelper().put(PropertyKeys.value, _value);
    }

    public java.lang.String getSelectionMode() {
        return (String) getStateHelper().eval(PropertyKeys.selectionMode, null);
    }

    public void setSelectionMode(java.lang.String _selectionMode) {
        getStateHelper().put(PropertyKeys.selectionMode, _selectionMode);
    }

    public java.lang.Object getSelection() {
        return (java.lang.Object) getStateHelper().eval(PropertyKeys.selection, null);
    }

    public void setSelection(java.lang.Object _selection) {
        getStateHelper().put(PropertyKeys.selection, _selection);
    }

    public boolean isRequired() {
        return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.required, false);
    }

    public void setRequired(boolean _required) {
        getStateHelper().put(PropertyKeys.required, _required);
    }

    public java.lang.String getRequiredMessage() {
        return (java.lang.String) getStateHelper().eval(PropertyKeys.requiredMessage, null);
    }

    public void setRequiredMessage(java.lang.String _requiredMessage) {
        getStateHelper().put(PropertyKeys.requiredMessage, _requiredMessage);
    }

    public boolean isSkipChildren() {
        return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.skipChildren, false);
    }

    public void setSkipChildren(boolean _skipChildren) {
        getStateHelper().put(PropertyKeys.skipChildren, _skipChildren);
    }

    public boolean isShowUnselectableCheckbox() {
        return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.showUnselectableCheckbox, false);
    }

    public void setShowUnselectableCheckbox(boolean _showUnselectableCheckbox) {
        getStateHelper().put(PropertyKeys.showUnselectableCheckbox, _showUnselectableCheckbox);
    }

    public Object getLocalSelectedNodes() {
        return getStateHelper().get(PropertyKeys.selection);
    }

    protected TreeNode findTreeNode(TreeNode searchRoot, String rowKey) {
        if (rowKey == null || searchRoot == null) {
            return null;
        }

        if (rowKey.equals("root")) {
            return this.getValue();
        }

        String[] paths = rowKey.split(SEPARATOR);

        if (paths.length == 0) {
            return null;
        }

        int childIndex = Integer.parseInt(paths[0]);
        if (childIndex >= searchRoot.getChildren().size()) {
            return null;
        }

        searchRoot = searchRoot.getChildren().get(childIndex);

        if (paths.length == 1) {
            return searchRoot;
        }
        else {
            String relativeRowKey = rowKey.substring(rowKey.indexOf(SEPARATOR) + 1);

            return findTreeNode(searchRoot, relativeRowKey);
        }
    }

    public void buildRowKeys(TreeNode node) {
        int childCount = node.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                TreeNode childNode = node.getChildren().get(i);
                if (childNode.isSelected()) {
                    addToPreselection(childNode);
                }

                String childRowKey = (node.getParent() == null) ? String.valueOf(i) : node.getRowKey() + "_" + i;
                childNode.setRowKey(childRowKey);
                buildRowKeys(childNode);
            }
        }
    }

    public void populateRowKeys(TreeNode node, List keys) {
        if (node != null) {
            int childCount = node.getChildCount();
            if (childCount > 0) {
                for (int i = 0; i < childCount; i++) {
                    TreeNode childNode = node.getChildren().get(i);
                    keys.add(childNode.getRowKey());
                    populateRowKeys(childNode, keys);
                }
            }
        }
    }

    public void updateRowKeys(TreeNode node) {
        int childCount = node.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                TreeNode childNode = node.getChildren().get(i);

                String childRowKey = (node.getParent() == null) ? String.valueOf(i) : node.getRowKey() + "_" + i;
                childNode.setRowKey(childRowKey);
                updateRowKeys(childNode);
            }
        }
    }

    public void initPreselection() {
        ValueExpression ve = this.getValueExpression(UITree.PropertyKeys.selection.toString());
        if (ve != null) {
            if (preselection != null) {
                String selectionMode = this.getSelectionMode();
                if (selectionMode != null) {
                    if (selectionMode.equals("single")) {
                        if (this.preselection.size() > 0) {
                            ve.setValue(FacesContext.getCurrentInstance().getELContext(), this.preselection.get(0));
                        }
                    }
                    else {
                        ve.setValue(FacesContext.getCurrentInstance().getELContext(), this.preselection.toArray(new TreeNode[0]));
                    }

                    this.preselection = null;
                }
            }
            else {
                ve.setValue(FacesContext.getCurrentInstance().getELContext(), null);
            }
        }
    }

    private void updateSelectedNodes(TreeNode node) {
        int childCount = node.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                TreeNode childNode = node.getChildren().get(i);
                if (childNode.isSelected()) {
                    addToPreselection(childNode);
                }

                updateSelectedNodes(childNode);
            }
        }
    }

    public void refreshSelectedNodeKeys() {
        TreeNode root = this.getValue();
        this.preselection = null;
        updateSelectedNodes(root);
        initPreselection();
    }

    public String getSelectedRowKeysAsString() {
        String value = null;
        Object selection = this.getSelection();
        String selectionMode = this.getSelectionMode();

        if (selection != null) {
            if (selectionMode.equals("single")) {
                TreeNode node = (TreeNode) selection;
                value = node.getRowKey();
            }
            else {
                TreeNode[] nodes = (TreeNode[]) selection;
                StringBuilder builder = SharedStringBuilder.get(SB_GET_SELECTED_ROW_KEYS_AS_STRING);

                for (int i = 0; i < nodes.length; i++) {
                    builder.append(nodes[i].getRowKey());
                    if (i != (nodes.length - 1)) {
                        builder.append(",");
                    }
                }

                value = builder.toString();
            }
        }

        return value;
    }

    @Override
    public String getContainerClientId(FacesContext context) {
        String clientId = super.getContainerClientId(context);
        String _rowKey = this.getRowKey();

        if (_rowKey == null) {
            return clientId;
        }
        else {
            StringBuilder builder = SharedStringBuilder.get(context, SB_GET_CONTAINER_CLIENT_ID);

            return builder.append(clientId).append(UINamingContainer.getSeparatorChar(context)).append(rowKey).toString();
        }
    }

    @Override
    public void queueEvent(FacesEvent event) {
        super.queueEvent(new WrapperEvent(this, event, getRowKey()));
    }

    @Override
    public void broadcast(FacesEvent event) throws AbortProcessingException {
        if (!(event instanceof WrapperEvent)) {
            super.broadcast(event);
            return;
        }

        FacesContext context = FacesContext.getCurrentInstance();
        WrapperEvent wrapperEvent = (WrapperEvent) event;
        String oldRowKey = this.getRowKey();
        setRowKey(wrapperEvent.getRowKey());
        FacesEvent originalEvent = wrapperEvent.getFacesEvent();
        UIComponent source = (UIComponent) originalEvent.getSource();
        UIComponent compositeParent = null;

        try {
            if (!UIComponent.isCompositeComponent(source)) {
                compositeParent = UIComponent.getCompositeComponentParent(source);
            }
            if (compositeParent != null) {
                compositeParent.pushComponentToEL(context, null);
            }
            source.pushComponentToEL(context, null);
            source.broadcast(originalEvent);
        }
        finally {
            source.popComponentFromEL(context);
            if (compositeParent != null) {
                compositeParent.popComponentFromEL(context);
            }
        }

        setRowKey(oldRowKey);
    }

    @Override
    public void processDecodes(FacesContext context) {
        if (!isRendered()) {
            return;
        }

        pushComponentToEL(context, this);

        Map saved = (Map) getStateHelper().get(PropertyKeys.saved);
        if (saved == null) {
            getStateHelper().remove(PropertyKeys.saved);
        }

        processNodes(context, PhaseId.APPLY_REQUEST_VALUES);

        try {
            decode(context);
        }
        catch (RuntimeException e) {
            context.renderResponse();
            throw e;
        }

        popComponentFromEL(context);
    }

    @Override
    public void processValidators(FacesContext context) {
        if (!isRendered()) {
            return;
        }

        pushComponentToEL(context, this);
        Application application = context.getApplication();
        application.publishEvent(context, PreValidateEvent.class, this);
        processNodes(context, PhaseId.PROCESS_VALIDATIONS);
        validateSelection(context);
        application.publishEvent(context, PostValidateEvent.class, this);
        popComponentFromEL(context);
    }

    protected void validateSelection(FacesContext context) {
        String selectionMode = this.getSelectionMode();
        if (selectionMode != null && this.isRequired()) {
            boolean valid = true;
            Object selection = this.getSelection();

            if (selectionMode.equals("single")) {
                if (selection == null) {
                    valid = false;
                }
            }
            else {
                TreeNode[] selectionArray = (TreeNode[]) selection;
                if (selectionArray.length == 0) {
                    valid = false;
                }
            }

            if (!valid) {
                String requiredMessage = this.getRequiredMessage();
                FacesMessage msg;

                if (requiredMessage != null) {
                    msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, requiredMessage, requiredMessage);
                }
                else {
                    msg = MessageFactory.getMessage(REQUIRED_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, new Object[]{this.getClientId(context)});
                }

                context.addMessage(this.getClientId(context), msg);
                context.validationFailed();
                context.renderResponse();
            }
        }
    }

    @Override
    public void processUpdates(FacesContext context) {
        if (!isRendered()) {
            return;
        }

        pushComponentToEL(context, this);

        processNodes(context, PhaseId.UPDATE_MODEL_VALUES);

        updateSelection(context);

        popComponentFromEL(context);
    }

    public void updateSelection(FacesContext context) {
        String selectionMode = this.getSelectionMode();
        ValueExpression selectionVE = this.getValueExpression(UITree.PropertyKeys.selection.toString());

        if (selectionMode != null && selectionVE != null) {
            Object selection = this.getLocalSelectedNodes();
            Object previousSelection = selectionVE.getValue(context.getELContext());

            if (selectionMode.equals("single")) {
                if (previousSelection != null) {
                    ((TreeNode) previousSelection).setSelected(false);
                }
                if (selection != null) {
                    ((TreeNode) selection).setSelected(true);
                }
            }
            else {
                TreeNode[] previousSelections = (TreeNode[]) previousSelection;
                TreeNode[] selections = (TreeNode[]) selection;

                if (previousSelections != null) {
                    for (TreeNode node : previousSelections) {
                        node.setSelected(false);
                    }
                }

                if (selections != null) {
                    for (TreeNode node : selections) {
                        node.setSelected(true);
                    }
                }
            }

            selectionVE.setValue(context.getELContext(), selection);
            setSelection(null);
        }
    }

    protected void processNodes(FacesContext context, PhaseId phaseId) {
        if (this.isSkipChildren()) {
            return;
        }

        processFacets(context, phaseId);
        processColumnFacets(context, phaseId);

        TreeNode root = getValue();
        if (root != null) {
            processNode(context, phaseId, root, null);
        }

        setRowKey(null);
    }

    protected void processNode(FacesContext context, PhaseId phaseId, TreeNode treeNode, String rowKey) {
        processColumnChildren(context, phaseId, rowKey);

        //process child nodes if node is expanded or node itself is the root
        if (shouldVisitNode(treeNode)) {
            int childIndex = 0;
            for (Iterator iterator = treeNode.getChildren().iterator(); iterator.hasNext();) {
                String childRowKey = rowKey == null ? String.valueOf(childIndex) : rowKey + SEPARATOR + childIndex;

                processNode(context, phaseId, iterator.next(), childRowKey);

                childIndex++;
            }
        }
    }

    protected void processFacets(FacesContext context, PhaseId phaseId) {
        setRowKey(null);

        if (getFacetCount() > 0) {
            for (UIComponent facet : getFacets().values()) {
                if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
                    facet.processDecodes(context);
                }
                else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
                    facet.processValidators(context);
                }
                else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
                    facet.processUpdates(context);
                }
                else {
                    throw new IllegalArgumentException();
                }
            }
        }
    }

    protected void processColumnFacets(FacesContext context, PhaseId phaseId) {
        setRowKey(null);

        for (UIComponent child : getChildren()) {
            if (child instanceof UIColumn && child.isRendered()) {
                UIColumn column = (UIColumn) child;

                if (column.getFacetCount() > 0) {
                    for (UIComponent columnFacet : column.getFacets().values()) {
                        if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
                            columnFacet.processDecodes(context);
                        }
                        else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
                            columnFacet.processValidators(context);
                        }
                        else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
                            columnFacet.processUpdates(context);
                        }
                        else {
                            throw new IllegalArgumentException();
                        }
                    }
                }
            }
        }
    }

    protected void processColumnChildren(FacesContext context, PhaseId phaseId, String nodeKey) {
        setRowKey(nodeKey);

        if (nodeKey == null) {
            return;
        }

        for (UIComponent child : getChildren()) {
            if (child.isRendered()) {
                if (child instanceof UIColumn) {
                    for (UIComponent grandkid : child.getChildren()) {
                        if (grandkid.isRendered()) {
                            processComponent(context, grandkid, phaseId);
                        }
                    }
                }
                else {
                    processComponent(context, child, phaseId);
                }
            }

        }
    }

    protected void processComponent(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);
        }
        else {
            throw new IllegalArgumentException();
        }
    }

    private void saveDescendantState() {
        FacesContext context = getFacesContext();

        for (UIComponent child : getChildren()) {
            saveDescendantState(child, context);
        }
    }

    private 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 clientId = component.getClientId(context);

            if (saved == null) {
                state = new SavedState();
                getStateHelper().put(PropertyKeys.saved, clientId, state);
            }

            if (state == null) {
                state = saved.get(clientId);

                if (state == null) {
                    state = new SavedState();
                    getStateHelper().put(PropertyKeys.saved, clientId, state);
                }
            }

            state.setValue(input.getLocalValue());
            state.setValid(input.isValid());
            state.setSubmittedValue(input.getSubmittedValue());
            state.setLocalValueSet(input.isLocalValueSet());
        }

        for (UIComponent uiComponent : component.getChildren()) {
            saveDescendantState(uiComponent, context);
        }

        if (component.getFacetCount() > 0) {
            for (UIComponent facet : component.getFacets().values()) {
                saveDescendantState(facet, context);
            }
        }
    }

    private void restoreDescendantState() {
        FacesContext context = getFacesContext();

        for (UIComponent child : getChildren()) {
            restoreDescendantState(child, context);
        }
    }

    private void restoreDescendantState(UIComponent component, FacesContext context) {
        //force id reset
        String id = component.getId();
        component.setId(id);

        Map saved = (Map) getStateHelper().get(PropertyKeys.saved);

        if (component instanceof EditableValueHolder) {
            EditableValueHolder input = (EditableValueHolder) component;
            String clientId = component.getClientId(context);

            SavedState state = saved.get(clientId);
            if (state == null) {
                state = new SavedState();
            }

            input.setValue(state.getValue());
            input.setValid(state.isValid());
            input.setSubmittedValue(state.getSubmittedValue());
            input.setLocalValueSet(state.isLocalValueSet());
        }
        for (UIComponent kid : component.getChildren()) {
            restoreDescendantState(kid, context);
        }

        if (component.getFacetCount() > 0) {
            for (UIComponent facet : component.getFacets().values()) {
                restoreDescendantState(facet, context);
            }
        }
    }

    @Override
    public boolean visitTree(VisitContext context, VisitCallback callback) {
        if (!isVisitable(context)) {
            return false;
        }

        FacesContext facesContext = context.getFacesContext();
        boolean visitNodes = requiresIteration(facesContext, context);

        String oldRowKey = getRowKey();
        if (visitNodes) {
            setRowKey(null);
        }

        pushComponentToEL(facesContext, null);

        try {
            VisitResult result = context.invokeVisitCallback(this, callback);

            if (result == VisitResult.COMPLETE) {
                return true;
            }

            if ((result == VisitResult.ACCEPT) && doVisitChildren(context)) {
                if (visitFacets(context, callback, visitNodes)) {
                    return true;
                }

                if (visitNodes(context, callback, visitNodes)) {
                    return true;
                }
            }
        }
        finally {
            popComponentFromEL(facesContext);

            if (visitNodes) {
                setRowKey(oldRowKey);
            }
        }

        return false;
    }

    protected boolean doVisitChildren(VisitContext context) {
        Collection idsToVisit = context.getSubtreeIdsToVisit(this);

        return (!idsToVisit.isEmpty());
    }

    protected boolean visitFacets(VisitContext context, VisitCallback callback, boolean visitNodes) {
        if (visitNodes) {
            setRowKey(null);
        }

        if (getFacetCount() > 0) {
            for (UIComponent facet : getFacets().values()) {
                if (facet.visitTree(context, callback)) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean visitColumns(VisitContext context, VisitCallback callback, String rowKey) {
        setRowKey(rowKey);

        if (rowKey == null) {
            return false;
        }

        TreeNode rowNode = this.getRowNode();
        String treeNodeType = null;
        if (rowNode != null) {
            treeNodeType = rowNode.getType();
        }

        if (getChildCount() > 0) {
            for (UIComponent child : getChildren()) {
                if (child instanceof Columns) {
                    Columns uicolumns = (Columns) child;
                    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 if (child instanceof UIColumn) {
                    if (child instanceof UITreeNode) {
                        UITreeNode uiTreeNode = (UITreeNode) child;
                        if (treeNodeType != null && !treeNodeType.equals(uiTreeNode.getType())) {
                            continue;
                        }
                    }
                    if (child.visitTree(context, callback)) {
                        return true;
                    }
                }
            }
        }

        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 visitNodes(VisitContext context, VisitCallback callback, boolean visitRows) {
        if (visitRows) {
            TreeNode root = getValue();
            if (root != null) {
                if (visitNode(context, callback, root, null)) {
                    return true;
                }
            }

            setRowKey(null);
        }

        return false;
    }

    protected boolean visitNode(VisitContext context, VisitCallback callback, TreeNode treeNode, String rowKey) {
        if (visitColumns(context, callback, rowKey)) {
            return true;
        }

        //visit child nodes if node is expanded or node itself is the root
        if (shouldVisitNode(treeNode)) {
            int childIndex = 0;
            for (Iterator iterator = treeNode.getChildren().iterator(); iterator.hasNext();) {
                String childRowKey = rowKey == null ? String.valueOf(childIndex) : rowKey + SEPARATOR + childIndex;

                if (visitNode(context, callback, iterator.next(), childRowKey)) {
                    return true;
                }

                childIndex++;
            }
        }

        return false;
    }

    public boolean isRTLRendering() {
        return rtl;
    }

    public void setRTLRendering(boolean rtl) {
        this.rtl = rtl;
    }

    protected boolean shouldVisitNode(TreeNode node) {
        return (node.isExpanded() || node.getParent() == null);
    }

    protected boolean requiresIteration(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);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy