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

com.sun.faces.component.CompositeComponentStackManager Maven / Gradle / Ivy

/*
 * 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.dev.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 com.sun.faces.component;

import javax.faces.context.FacesContext;
import javax.faces.component.UIComponent;
import javax.faces.view.Location;
import javax.faces.application.Resource;
import java.util.Stack;

/**
 * 

* CompositeComponentStackManager is responsible for managing the * two different composite component stacks currently used by Mojarra. *

* *

* The stacks are identified by the {@link StackType} enum which has two elements, * TreeCreation and Evaluation. *

* *

* The TreeCreation stack represents the composite components that * have been pushed by the TagHandlers responsible for building the tree. *

* *

* The Evaluation stack is used by the EL in order to properly * resolve nested composite component expressions. *

*/ public class CompositeComponentStackManager { private static final String MANAGER_KEY = CompositeComponentStackManager.class.getName(); public enum StackType { TreeCreation, Evaluation } private StackHandler treeCreation = new TreeCreationStackHandler(); private StackHandler runtime = new RuntimeStackHandler(); private FacesContext ctx; // ------------------------------------------------------------ Constructors private CompositeComponentStackManager(FacesContext ctx) { this.ctx = ctx; } // ---------------------------------------------------------- Public Methods /** * @param ctx the FacesContext for the current request * @return the CompositeComponentStackManager for the current * request */ public static CompositeComponentStackManager getManager(FacesContext ctx) { CompositeComponentStackManager manager = (CompositeComponentStackManager) ctx.getAttributes().get(MANAGER_KEY); if (manager == null) { manager = new CompositeComponentStackManager(ctx); ctx.getAttributes().put(MANAGER_KEY, manager); } return manager; } /** *

* Pushes the specified composite component to the Evaluation * stack. *

* * @param compositeComponent the component to push * @return true if the component was pushed, otherwise * returns false */ public boolean push(UIComponent compositeComponent) { return getStackHandler(StackType.Evaluation).push(compositeComponent); } /** *

* Pushes the specified composite component to the desired StackType * stack. *

* * @param compositeComponent the component to push * @param stackType the stack to push to the component to * @return true if the component was pushed, otherwise * returns false */ public boolean push(UIComponent compositeComponent, StackType stackType) { return getStackHandler(stackType).push(compositeComponent); } /** *

* Pushes a component derived by the push logic to the Evaluation * stack. *

* * @return true if the component was pushed, otherwise * returns false */ public boolean push() { return getStackHandler(StackType.Evaluation).push(); } /** *

* Pushes a component derived by the push logic to the specified stack. *

* * @param stackType the stack to push to the component to * * @return true if the component was pushed, otherwise * returns false */ public boolean push(StackType stackType) { return getStackHandler(stackType).push(); } /** *

* Pops the top-level component from the stack. *

* * @param stackType the stack to pop the top level component from */ public void pop(StackType stackType) { getStackHandler(stackType).pop(); } /** *

* Pops the top-level component from the Evaluation stack. *

*/ public void pop() { getStackHandler(StackType.Evaluation).pop(); } /** * @return the top-level component from the Evaluation stack * without removing the element */ public UIComponent peek() { return getStackHandler(StackType.Evaluation).peek(); } /** * @param stackType the stack to push to the component to * * @return the top-level component from the specified stack * without removing the element */ public UIComponent peek(StackType stackType) { return getStackHandler(stackType).peek(); } public UIComponent getParentCompositeComponent(StackType stackType, FacesContext ctx, UIComponent forComponent) { return getStackHandler(stackType).getParentCompositeComponent(ctx, forComponent); } public UIComponent findCompositeComponentUsingLocation(FacesContext ctx, Location location) { StackHandler sh = getStackHandler(StackType.TreeCreation); Stack s = sh.getStack(false); if (s != null) { String path = location.getPath(); for (int i = s.size(); i > 0; i--) { UIComponent cc = s.get(i - 1); Resource r = (Resource) cc.getAttributes().get(Resource.COMPONENT_RESOURCE_KEY); if (path.endsWith('/' + r.getResourceName()) && path.contains(r.getLibraryName())) { return cc; } } } else { // runtime eval String path = location.getPath(); UIComponent cc = UIComponent.getCurrentCompositeComponent(ctx); while (cc != null) { Resource r = (Resource) cc.getAttributes().get(Resource.COMPONENT_RESOURCE_KEY); if (path.endsWith('/' + r.getResourceName()) && path.contains(r.getLibraryName())) { return cc; } cc = UIComponent.getCompositeComponentParent(cc); } } return null; } // --------------------------------------------------------- Private Methods private StackHandler getStackHandler(StackType type) { StackHandler handler = null; switch (type) { case TreeCreation: handler = treeCreation; break; case Evaluation: handler = runtime; break; } return handler; } // ------------------------------------------------------ Private Interfaces private interface StackHandler { boolean push(UIComponent compositeComponent); boolean push(); void pop(); UIComponent peek(); UIComponent getParentCompositeComponent(FacesContext ctx, UIComponent forComponent); void delete(); Stack getStack(boolean create); } // ---------------------------------------------------------- Nested Classes private abstract class BaseStackHandler implements StackHandler { protected Stack stack; // ------------------------------------------- Methods from StackHandler public void delete() { stack = null; } public Stack getStack(boolean create) { if (stack == null && create) { stack = new Stack(); } return stack; } public UIComponent peek() { if (stack != null && !stack.isEmpty()) { return stack.peek(); } return null; } } // END BaseStackHandler private final class RuntimeStackHandler extends BaseStackHandler { // ------------------------------------------- Methods from StackHandler public void delete() { Stack s = getStack(false); if (s != null) { s.clear(); } } public void pop() { Stack s = getStack(false); if (s != null && !s.isEmpty()) { s.pop(); } } public boolean push() { return push(null); } public boolean push(UIComponent compositeComponent) { Stack tstack = CompositeComponentStackManager.this.treeCreation.getStack(false); Stack stack = getStack(false); UIComponent ccp; if (tstack != null) { // We have access to the stack of composite components // the tree creation process has made available. // Since we can' reliably access the parent composite component // of the current composite component, use the index of the // current composite component within the stack to locate the // parent. ccp = compositeComponent; } else { // no tree creation stack available, so use the runtime stack. // If the current stack isn't empty, then use the component // on the stack as the current composite component. stack = getStack(false); if (compositeComponent == null) { if (stack != null && !stack.isEmpty()) { ccp = getCompositeParent(stack.peek()); } else { ccp = getCompositeParent((UIComponent .getCurrentCompositeComponent(ctx))); } } else { ccp = compositeComponent; } } if (ccp != null) { if (stack == null) { stack = getStack(true); } stack.push(ccp); return true; } return false; } public UIComponent getParentCompositeComponent(FacesContext ctx, UIComponent forComponent) { return getCompositeParent(forComponent); } // ----------------------------------------------------- Private Methods private UIComponent getCompositeParent(UIComponent comp) { return UIComponent.getCompositeComponentParent(comp); } } // END RuntimeStackHandler private final class TreeCreationStackHandler extends BaseStackHandler { // ------------------------------------------- Methods from StackHandler public void pop() { Stack s = getStack(false); if (s != null && !stack.isEmpty()) { stack.pop(); if (stack.isEmpty()) { delete(); } } } public boolean push() { return false; } public boolean push(UIComponent compositeComponent) { if (compositeComponent != null) { assert (UIComponent.isCompositeComponent(compositeComponent)); Stack s = getStack(true); s.push(compositeComponent); return true; } return false; } public UIComponent getParentCompositeComponent(FacesContext ctx, UIComponent forComponent) { Stack s = getStack(false); if (s == null) { return null; } else { int idx = s.indexOf(forComponent); if (idx == 0) { // no parent return null; } return (s.get(idx - 1)); } } } // END TreeCreationStackHandler }