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

com.sun.jsftemplating.handlers.ComponentHandlers Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://jsftemplating.dev.java.net/cddl1.html or
 * jsftemplating/cddl1.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at jsftemplating/cddl1.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */
/*
 * ComponentHandlers.java
 *
 * Created on December 6, 2004, 11:06 PM
 */
package com.sun.jsftemplating.handlers;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

import com.sun.jsftemplating.annotation.Handler;
import com.sun.jsftemplating.annotation.HandlerInput;
import com.sun.jsftemplating.annotation.HandlerOutput;
import com.sun.jsftemplating.component.ComponentUtil;
import com.sun.jsftemplating.layout.LayoutDefinitionManager;
import com.sun.jsftemplating.layout.LayoutViewHandler;
import com.sun.jsftemplating.layout.descriptors.LayoutComponent;
import com.sun.jsftemplating.layout.descriptors.LayoutElement;
import com.sun.jsftemplating.layout.descriptors.LayoutElementBase;
import com.sun.jsftemplating.layout.descriptors.handler.HandlerContext;
import com.sun.jsftemplating.util.LayoutElementUtil;


/**
 *  

This class contains * {@link com.sun.jsftemplating.layout.descriptors.handler.Handler} * methods that perform component functions.

* * @author Ken Paulsen ([email protected]) */ public class ComponentHandlers { /** *

Default Constructor.

*/ public ComponentHandlers() { } /** *

This handler returns the children of the given * UIComponent.

* *

Input value: "parent" -- Type: UIComponent

* *

Output value: "children" -- Type: java.util.List

*

Output value: "size" -- Type: java.lang.Integer

* * @param context The HandlerContext. */ @Handler(id="getUIComponentChildren", input={ @HandlerInput(name="parent", type=UIComponent.class, required=true)}, output={ @HandlerOutput(name="children", type=List.class), @HandlerOutput(name="size", type=Integer.class)}) public static void getChildren(HandlerContext context) { UIComponent parent = (UIComponent) context.getInputValue("parent"); List list = parent.getChildren(); context.setOutputValue("children", list); context.setOutputValue("size", new Integer(list.size())); } /** *

This handler replaces the given old UIComponent in the * UIComponent tree with the given new * UIComponent. If the new UIComponent is not * specified or is null, the old UIComponent will simply * be removed.

* *

Input value: "old" -- Type: UIComponent

*

Input value: "new" -- Type: UIComponent

* * @param context The HandlerContext. */ @Handler(id="replaceUIComponent", input={ @HandlerInput(name="old", type=UIComponent.class, required=true), @HandlerInput(name="new", type=UIComponent.class, required=false)} ) public static void replaceUIComponent(HandlerContext context) { // Get the old component which is to be replaced UIComponent oldComp = (UIComponent) context.getInputValue("old"); if (oldComp == null) { throw new IllegalArgumentException( "You must provide a non-null value for 'component'."); } // Check for a replacement UIComponent UIComponent newComp = (UIComponent) context.getInputValue("new"); // Get the child UIComponent list... List list = oldComp.getParent().getChildren(); if (newComp == null) { // Nothing to replace it with, just do a remove... list.remove(oldComp); } else { // Find the index to put the new UIComponent in the right place int index = list.indexOf(oldComp); list.set(index, newComp); } } /** *

This will build a UIComponent tree from a * {@link LayoutElement}. You must pass in the {@link LayoutElement} * that will be used to create the UIComponent tree. * You may optionally pass in the parent UIComponent * which will serve as the parent for the newly created * UIComponent tree. The resulting * UIComponent tree will be returned via the * result output value. If more than 1 root node exists * for the given LayoutElement, the last added to the * parent will be returned. Typically, you will pass in * a {@link LayoutComponent} as the layoutElement so * there will only be 1.

* *

It is recommended that you *do* supply the parent since EL * expressions may depend on this when creating the * UIComponent tree.

* *

One possible use case for calling this method would be to have a * dynamic "id" property of a {@link LayoutComponent}, call this * method multiple times with different values set in the "id" * property. Remember, that you should not change a * {@link LayoutComponent} (or any {@link LayoutElement}) directly. * It is only safe to have dynamic values through EL bindings #{}.

* *

Another reason to use this handler is to cause a portion of a * UIComponent tree to be recreated. This of often * desirable during Ajax requests so that factory options can be * reevaluated.

* *

Input value: "layoutElement" -- Type: LayoutElement

*

Input value: "parent" -- Type: UIComponent

* *

Output value: "result" -- Type: UIComponent

* * @param context The HandlerContext. */ @Handler(id="buildUIComponentTree", input={ @HandlerInput(name="layoutElement", type=LayoutElement.class, required=true), @HandlerInput(name="parent", type=UIComponent.class, required=false)}, output={ @HandlerOutput(name="result", type=UIComponent.class)} ) public static void buildUIComponentTree(HandlerContext context) { LayoutElement desc = (LayoutElement) context.getInputValue("layoutElement"); UIComponent parent = (UIComponent) context.getInputValue("parent"); // If they didn't give us a parent, make one one up... if (parent == null) { parent = new UIViewRoot(); ((UIViewRoot) parent).setViewId("fake"); } // Build it... FacesContext facesCtx = context.getFacesContext(); if (desc instanceof LayoutComponent) { // Special case if LayoutComponent is the root node element // The LayoutViewHandler assumes that the root node is not used // because it was written assuming that the LayoutDefinition was // always going to be passed in. The result is that it ignores // the LayoutElement that is passed in and goes striaight to the // children. This isn't what we want. Process the child here, // then continue as normal. UIComponent tmpParent = ((LayoutComponent) desc).getChild(facesCtx, parent); LayoutViewHandler.buildUIComponentTree(facesCtx, tmpParent, desc); } else { // Process normally (which in this path is probably not normal) LayoutViewHandler.buildUIComponentTree(facesCtx, parent, desc); } // Get the result to return... String id = desc.getId(facesCtx, parent); UIComponent result = parent.findComponent(id); if (result == null) { // First see if we can find it in the facet Map if (desc instanceof LayoutComponent) { result = parent.getFacets().get(id); } else { // FIXME: find a way to find a "facet child" if the root LayoutElement is not a LayoutComponent } if (result == null) { // Still not found, check children... List children = parent.getChildren(); if (children.size() > 0) { // Return the last child added b/c we want to make sure // we're returning something that we added, not something // that already existed. While not perfect, this is // reasonable. result = children.get(children.size() -1); } } } // Set the output... context.setOutputValue("result", result); } /** *

This handler creates a UIComponent. It requires you * to pass in the componentType (type) and returns the * new component via the output parameter component.

* *

Input value: "type" -- Type: String

*

Input value: "parent" -- Type: UIComponent

* *

Output value: "component" -- Type: UIComponent

* * @param context The {@link HandlerContext}. */ @Handler(id="createComponent", input={ @HandlerInput(name="type", type=String.class, required=true), @HandlerInput(name="id", type=String.class, required=false), @HandlerInput(name="parent", type=UIComponent.class, required=false)}, output={ @HandlerOutput(name="component", type=UIComponent.class)} ) public static void createComponent(HandlerContext context) { // Get the input... String type = (String) context.getInputValue("type"); UIComponent parent = (UIComponent) context.getInputValue("parent"); String id = (String) context.getInputValue("id"); if (id == null) { id = LayoutElementUtil.getGeneratedId(type); } // Create a LayoutComponent... FacesContext ctx = context.getFacesContext(); LayoutComponent desc = new LayoutComponent((LayoutComponent) null, id, LayoutDefinitionManager.getGlobalComponentType(ctx, type)); // Create the component... UIComponent component = ComponentUtil.getInstance(ctx).createChildComponent( ctx, desc, parent); // Return the result... context.setOutputValue("component", component); } /** *

This handler sets a UIComponent attribute / * property.

* *

Input value: "component" -- Type: UIComponent

*

Input value: "property" -- Type: String

*

Input value: "value" -- Type: Object

* * @param context The HandlerContext. */ @Handler(id="setUIComponentProperty", input={ @HandlerInput(name="component", type=UIComponent.class, required=true), @HandlerInput(name="property", type=String.class, required=true), @HandlerInput(name="value")}) public static void setComponentProperty(HandlerContext context) { UIComponent component = (UIComponent) context.getInputValue("component"); String propName = (String) context.getInputValue("property"); Object value = context.getInputValue("value"); // Set the attribute or property value component.getAttributes().put(propName, value); } /** *

This handler finds the requested UIComponent by * clientId. It takes clientId as an input * parameter, and returns component as an output * parameter.

*/ @Handler(id="getUIComponent", input={ @HandlerInput(name="clientId", type=String.class, required=true)}, output={ @HandlerOutput(name="component", type=UIComponent.class)}) public static void getUIComponent(HandlerContext context) { UIComponent viewRoot = context.getFacesContext().getViewRoot(); String clientId = (String) context.getInputValue("clientId"); context.setOutputValue("component", viewRoot.findComponent(clientId)); } /** *

This handler retrieves a property from the given * UIComponent. It expects component and * name as an input parameters, and returns * value as an output parameter containing the value of * the property.

*/ @Handler(id="getUIComponentProperty", input={ @HandlerInput(name="component", type=UIComponent.class, required=true), @HandlerInput(name="name", type=String.class, required=true)}, output={ @HandlerOutput(name="value", type=Object.class)}) public static void getUIComponentProperty(HandlerContext context) { UIComponent comp = (UIComponent) context.getInputValue("component"); String name = (String) context.getInputValue("name"); if ((comp == null) || (name == null)) { throw new IllegalArgumentException("This Handler requires non-null" + " values for 'component' and 'name'. 'component' was" + " specified as '" + context.getHandler().getInputValue("component") + "' and evaluated to '" + comp + "'. 'name' was" + " specified as '" + context.getHandler().getInputValue("name") + "' and evaluated to '" + name + "'."); } Object value = comp.getAttributes().get(name); context.setOutputValue("value", value); } /** *

This handler retrieves the requested the "facet" from the given * UIComponent. component or * clientId for the component must be passed in. The * facet name must also be specified. It will return * the UIComponent found (or null) in the * value output parameter.

* * @param context The {@link HandlerContext}. */ @Handler(id="getFacet", input={ @HandlerInput(name="clientId", type=String.class, required=false), @HandlerInput(name="component", type=UIComponent.class, required=false), @HandlerInput(name="name", type=String.class, required=true)}, output={ @HandlerOutput(name="value", type=UIComponent.class)}) public static void getFacet(HandlerContext context) { // Get the UIComponent to use UIComponent comp = getUIComponentFromInput(context); // Get the facet name String clientId = "" + (String) context.getInputValue("name"); // Look for the facet UIComponent value = null; if (comp != null) { value = comp.getFacets().get(clientId); } // Return the UIComponent (or null) context.setOutputValue("value", value); } /** *

This handler encodes the given UIComponent. You can * specify the UIComponent by clientId, or * pass it in directly via the component input * parameter.

* * @param context The {@link HandlerContext}. */ @Handler(id="encodeUIComponent", input={ @HandlerInput(name="clientId", type=String.class, required=false), @HandlerInput(name="component", type=UIComponent.class, required=false)} ) public static void encode(HandlerContext context) throws IOException { // Get the UIComponent to use UIComponent comp = getUIComponentFromInput(context); // Encode the component LayoutElementBase.encodeChild(context.getFacesContext(), comp); } /** *

This method simply helps resolve a UIComponent for * handlers that allow them to be specified via "component" or * "clientId". "component" takes precedence. If neither are * supplied, an IllegalArgumentException is thrown.

* * @param context The {@link HandlerContext}. * * @return The UIComponent or null (if clientId * did not resolve it). * * @throws IllegalArgumentException If neither "clientId" or * "component" are provided. */ private static UIComponent getUIComponentFromInput(HandlerContext context) { UIComponent comp = (UIComponent) context.getInputValue("component"); if (comp == null) { String clientId = (String) context.getInputValue("clientId"); if (clientId != null) { UIComponent viewRoot = context.getFacesContext().getViewRoot(); comp = viewRoot.findComponent(clientId); } else { throw new IllegalArgumentException( "You must specify the component to use, or a clientId to " + "locate the UIComponent to use."); } } // Return the UIComponent (may be null if clientId didn't resolve it) return comp; } /** *

This handler will print out the structure of a * UIComponent tree from the given UIComponent.

*/ @Handler(id="dumpUIComponentTree", input={ @HandlerInput(name="component", type=UIComponent.class, required=false)}, output={ @HandlerOutput(name="value", type=String.class)}) public static void dumpUIComponentTree(HandlerContext context) { // FIXME: Add flag to dump attributes also, perhaps facets should be optional as well? // Find the root UIComponent to use... UIComponent comp = (UIComponent) context.getInputValue("component"); if (comp == null) { Object eventObject = context.getEventObject(); if (eventObject instanceof UIComponent) { comp = (UIComponent) eventObject; } else { comp = context.getFacesContext().getViewRoot(); if (comp == null) { throw new IllegalArgumentException( "Unable to determine UIComponent to dump!"); } } } // Create the buffer and populate it... StringBuffer buf = new StringBuffer("UIComponent Tree:\n"); dumpTree(comp, buf, " "); context.setOutputValue("value", buf.toString()); } /** *

This method recurses through the UIComponent tree to * generate a String representation of its structure.

*/ private static void dumpTree(UIComponent comp, StringBuffer buf, String indent) { // First add the current UIComponent buf.append(indent + comp.getId() + " (" + comp.getClass().getName() + ") = (" + comp.getAttributes().get("value") + ")\n"); // Children... Iterator it = comp.getChildren().iterator(); if (it.hasNext()) { buf.append(indent + " Children:\n"); while (it.hasNext()) { dumpTree(it.next(), buf, indent + " "); } } // Facets... Map facetMap = comp.getFacets(); Iterator facetNames = facetMap.keySet().iterator(); if (facetNames.hasNext()) { while (facetNames.hasNext()) { String name = facetNames.next(); buf.append(indent + " Facet (" + name + "):\n"); dumpTree(facetMap.get(name), buf, indent + " "); } } } /** *

This handler will print out the structure of a * {@link LayoutElement} tree from the given LayoutElement.

*/ @Handler(id="dumpLayoutElementTree", input={ @HandlerInput(name="layoutElement", type=LayoutElement.class, required=false)}, output={ @HandlerOutput(name="value", type=String.class)}) public static void dumpLayoutElementTree(HandlerContext context) { // FIXME: Add flag to dump attributes also, perhaps facets should be optional as well? // Find the root UIComponent to use... LayoutElement elt = (LayoutElement) context.getInputValue("layoutElement"); if (elt == null) { elt = context.getLayoutElement(); if (elt == null) { throw new IllegalArgumentException( "Unable to determine LayoutElement to dump!"); } } // Create the buffer and populate it... StringBuffer buf = new StringBuffer("LayoutElement Tree:\n"); LayoutElementUtil.dumpTree(elt, buf, " "); context.setOutputValue("value", buf.toString()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy