/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package treevisit; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.logging.Logger; import javax.faces.component.UIComponent; import javax.faces.component.UIData; import javax.faces.component.UIViewRoot; 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.event.ActionEvent; import javax.faces.model.SelectItem; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; /** * <p>This bean has the methods that are used to illustrate * the tree visitor API</p> * */ @ManagedBean(name="treevisit") @SessionScoped public class Bean { // // Instance Variables // // List of SelectItems representing all client ids on the page private List<SelectItem> items; // List of ids selected by the end user private List<String> selectedIds; // List of ids visited by our partial tree visit. private List<String> visitedIds; // Just a silly data model that we can use for testing // UIData tree visiting. private List<RowData> testData; // Flag indicating whether or not we should visit rendered // subtrees only. private boolean visitRendered; // // Constructors // public Bean() { } // Returns a list containing a SelectItem corresponding to // every component client id in this component tree. public List<SelectItem> getItems() { if (items == null) items = loadItems(); return items; } // Returns the list of ids to visit public List<String> getSelectedIds() { return selectedIds; } // Sets the list of ids to visit public void setSelectedIds(List<String> selectedIds) { this.selectedIds = selectedIds; } // Returns the list of ids that were visited public List<String> getVisitedIds() { return visitedIds; } // Returns test data for UIData tree visit testing. public List<RowData> getTestData() { if (testData == null) testData = loadTestData(); return testData; } // Returns whether we should visit rendered components only public boolean getVisitRendered() { return visitRendered; } // Sets whether we shoudl visit rendered components only public void setVisitRendered(boolean visitRendered) { this.visitRendered = visitRendered; } // ActionListener that triggers a partial visit of the // selected ids. public void visit(ActionEvent ae) { // To perform a tree visit, we need three things: // 1. A VisitContext // 2. A VisitCallback // 3. A component at which to start the visit. // Get our VisitContext. We use PartialVisitContext since we // we only want to visit a subset of the component tree. FacesContext facesContext = FacesContext.getCurrentInstance(); EnumSet<VisitHint> hints = getVisitRendered() ? EnumSet.of(VisitHint.SKIP_UNRENDERED) : null; // Get ths ids to visit. Note that this must always be // non-null - otherwise we do a full visit. java.util.Collection<String> idsToVisit = getSelectedIds(); if (idsToVisit == null) idsToVisit = Collections.emptyList(); VisitContext visitContext = VisitContext.createVisitContext(facesContext, idsToVisit, hints); // Use CollectIdsVisitCallback to collect up visited ids CollectIdsVisitCallback visitCallback = new CollectIdsVisitCallback(); // Start the visit at the view root UIComponent viewRoot = facesContext.getViewRoot(); // Do the visit viewRoot.visitTree(visitContext, visitCallback); // And stash away the results visitedIds = visitCallback.getVisitedIds(); } // Loads the items - ie. the list of client ids for // all components in this document. private List<SelectItem> loadItems() { FacesContext facesContext = FacesContext.getCurrentInstance(); assert(facesContext != null); // We collect ids by performing a full tree visit. So, we // need a VisitContext, a VisitCallback, and a component to // initiate the visit on. VisitContext visitContext = VisitContext.createVisitContext(facesContext); CollectIdsVisitCallback visitCallback = new CollectIdsVisitCallback(); // Visit the subtree under the "mainGrid" component to populate // the visitable items list. UIComponent viewRoot = facesContext.getViewRoot(); UIComponent mainGrid = viewRoot.findComponent("form:mainGrid"); mainGrid.visitTree(visitContext, visitCallback); List<String> ids = visitCallback.getVisitedIds(); List<SelectItem> selectItems = new ArrayList<SelectItem>(ids.size()); for (String id : ids) { selectItems.add(new SelectItem(id)); } return selectItems; } // Load data that we use to test UIData tree visiting. private List<RowData> loadTestData() { List<RowData> data = new ArrayList<RowData>(5); for (int i = 0; i < 5; i++) { RowData rowData = new RowData("Row " + i); data.add(rowData); } return data; } // Callback class for collecting all ids static private class CollectIdsVisitCallback implements VisitCallback { // Collect ids in the list private List<String> ids = new ArrayList<String>(); // Performs the visit public VisitResult visit(VisitContext context, UIComponent component) { String clientId = component.getClientId(); // For the moment let's blow off any top-level auto-generated // ids. Facelets generates several UIInstructions components // which seem to be removed from the component tree at some point. // These might cause some confusion, so excluding this for our list. if (!clientId.startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) ids.add(clientId); return VisitResult.ACCEPT; } // Returns the collected ids public List<String> getVisitedIds() { return ids; } } // A silly little class that we use to pouplate a DataModel so // that we can test UIData.treeVisit(). static public class RowData { public RowData(String label) { this.label = label; } // Returns the label public String getLabel() { return label; } // Returns a count for the number of times this // row has been updated. public int getCount() { return count; } // Increments the count public void increment(ActionEvent ae) { count++; } private String label; private int count; } }