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

com.sun.jsftemplating.layout.descriptors.LayoutComposition 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 2007 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.jsftemplating.layout.descriptors;

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

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

import com.sun.jsftemplating.layout.LayoutDefinitionException;
import com.sun.jsftemplating.layout.LayoutDefinitionManager;
import com.sun.jsftemplating.layout.event.EncodeEvent;


/**
 * 

This concept is borrowed from * Facelets. A composition delegates to a "template" which performs * the layout for the content which exists in the body of this * composition component. The composition may have {@link LayoutDefine}s * to provide named blocks which the template may "insert" at the * appropriate place.

* *

This {@link LayoutElement} implements the behavior not only for * compositions, but also decorate, and include.

* * @author Jason Lee * @author Ken Paulsen ([email protected]) */ public class LayoutComposition extends LayoutElementBase { /** * @param parent * @param id */ public LayoutComposition(LayoutElement parent, String id) { super(parent, id); } /** *

Constructor.

*/ public LayoutComposition(LayoutElement parent, String id, boolean trimming) { super(parent, id); this.trimming = trimming; } /** *

true if a template filename is required to resolve to * a valid file. If the template filename is null, this property is * not used. false if it should be ignored when the does * not exist. The default is true.

*/ public boolean isRequired() { boolean result = true; if (required != null) { Object answer = resolveValue(FacesContext.getCurrentInstance(), null, required); if (answer != null) { result = Boolean.parseBoolean(answer.toString()); } } return result; } /** *

Setter for the template filename.

*/ public void setRequired(String required) { this.required = required; } /** *

Accessor for the template filename.

*/ public String getTemplate() { Object result = resolveValue(FacesContext.getCurrentInstance(), null, template); return (result == null) ? null : result.toString(); } /** *

Setter for the template filename.

*/ public void setTemplate(String template) { this.template = template; } /** *

true if all content outside of this LayoutComposition * should be thrown away.

*/ public boolean isTrimming() { return trimming; } /** *

Setter for the trimming property.

*/ public void setTrimming(boolean trimming) { this.trimming = trimming; } @Override protected boolean encodeThis(FacesContext context, UIComponent component) throws IOException { // The child LayoutElements for a LayoutComposition are consumed by // the template. The LayoutElements consumed here is the template. String templateName = getTemplate(); boolean result = true; if (templateName == null) { return result; } // Add this to the stack LayoutComposition.push(context, this); // Fire an encode event dispatchHandlers(context, ENCODE, new EncodeEvent(component)); LayoutElement template = null; try { template = LayoutDefinitionManager. getLayoutDefinition(context, templateName); } catch (LayoutDefinitionException ex) { if (isRequired()) { throw ex; } // If the template is optional ignore this error... } // Iterate over children if (template != null) { LayoutElement childElt = null; Iterator it = template.getChildLayoutElements().iterator(); while (it.hasNext()) { childElt = it.next(); childElt.encode(context, component); } result = false; } // Pop this from the stack LayoutComposition.pop(context); return result; } /** *

This handler pushes a value onto the * LayoutComposition Stack. In addition * it puts any parameters that are defined into the global parameter * Map so EL expressions can test to see if they may * reference one a composition parameter. However, this * Map should not be used to determine the value -- * instead the value should be obtained by looking through the * Stack of compositions.

*/ public static void push(FacesContext context, LayoutElement comp) { if (comp instanceof LayoutComposition) { // This should be the case... Map params = ((LayoutComposition) comp).getParameters(); if (params != null) { // Get the request-scoped global param map... Map globalParamMap = LayoutComposition.getGlobalParamMap(context); // Iterate over the params in this LayoutComposition and add // them to the global parameters that we're tracking. This // will flatten the hierarchy for the parameter values... but // that's ok, b/c we don't use this for obtaining the values // (normally), we use it to quickly detect if there are values. // We'll search the composition stack to actually obtain the // values. Iterator> it = params.entrySet().iterator(); Map.Entry entry = null; while (it.hasNext()) { entry = it.next(); globalParamMap.put(entry.getKey(), entry.getValue()); } } } getCompositionStack(context).push(comp); } /** *

This handler pops a value off the * LayoutComposition Stack.

*/ public static LayoutElement pop(FacesContext context) { return getCompositionStack(context).pop(); } /** *

This method returns the Stack used to keep track of * the {@link LayoutComposition}s that are used.

*/ public static Stack getCompositionStack(FacesContext context) { Map requestMap = (context == null) ? getTestMap() : context.getExternalContext().getRequestMap(); Stack stack = (Stack) requestMap.get(COMPOSITION_STACK_KEY); if (stack == null) { stack = new Stack(); requestMap.put(COMPOSITION_STACK_KEY, stack); } return stack; } /** *

This method retrieves a Map from the request scope for storing * ui:param NVPs. If the Map doesn't exist, it will be * created.

*/ public static Map getGlobalParamMap(FacesContext context) { // First get the requestMap Map requestMap = context.getExternalContext().getRequestMap(); Map paramMap = (Map) requestMap.get(GLOBAL_PARAM_MAP_KEY); if (paramMap == null) { // Hasn't been created yet, create it paramMap = new HashMap(); requestMap.put(GLOBAL_PARAM_MAP_KEY, paramMap); } return paramMap; } /** *

This method returns a Map that may be used to test * this code outside JSF.

*/ private static Map getTestMap() { // FIXME: Shouldn't we mock up the test environment instead of changing the code here? if (_testMap == null) { _testMap = new HashMap(); } return _testMap; } /** *

This method allows the composition stack to be set directly. * Normally this isn't needed, but if a seperate walk of the tree * must be done in the middle of an existing walk, this may be * necessary to reset and restore the Stack.

*/ public static Stack setCompositionStack(FacesContext context, Stack stack) { Map requestMap = context.getExternalContext().getRequestMap(); requestMap.put(COMPOSITION_STACK_KEY, stack); return stack; } /** *

This method searches the given the entire stack for a * template param with the given name.

* *

A "template param" is a name-value-pair associated with a * {@link LayoutComposition}. This enables overridable values to be * set on a LayoutComposition and consumed by the templates. This is * similar to a ui:define, except for values instead of * UIComponents.

* * @param eltList The List of LayoutCompositions in which * to search (must be non-null, NPE will be thrown). * @param name The name of the parameter to look for. */ public static Object findTemplateParam(List eltList, String name) { // FIME: Can I make this return a String? If this is at create time I should still have #{} or maybe ${} Iterator stackIt = eltList.iterator(); Object val = null; LayoutElement elt = null; LayoutComposition comp = null; while (stackIt.hasNext()) { elt = stackIt.next(); if (elt instanceof LayoutComposition) { // It should always be a LayoutComposition, however, I want // to be safe in case things change in the future. comp = (LayoutComposition) elt; if ((val = comp.getParameter(name)) != null) { break; } } } // Return the value (if found) return val; } /** *

This method returns the Map of parameter values, or * null if there are no parameter values for this * LayoutComposition.

*/ protected Map getParameters() { return _params; } /** *

This method returns the parameter value for the requested * parameter, or null if the requested parameter does * not exist.

*/ public Object getParameter(String name) { Object value = null; if (_params != null) { value = _params.get(name); } return value; } /** *

This method sets the given parameter name with the given parameter * value.

*/ public void setParameter(String name, Object value) { if (_params == null) { _params = new HashMap(); } _params.put(name, value); } private static final long serialVersionUID = 2L; /** *

This is the key used to store the LayoutComposition * stack.

*/ private static final String COMPOSITION_STACK_KEY = "_composition"; /** *

This is the key used to store the ui:param NVPs to assist in * determining if an EL is referencing one. It also may be used in * somone attempts to locate a ui:param after the composition stack * is no longer available (don't do that!).

*/ private static final String GLOBAL_PARAM_MAP_KEY = "_uiparamCacheMap"; /** *

This Map exists to allow test cases to run w/o an ExternalContext * "request map."

*/ private static Map _testMap = null; /** *

This is a Map of parameters that may be passed from * this LayoutComposition to the template.

*/ private Map _params = null; /** *

Flag to indicate that whether an exception should be thrown if the * template is not found.

*/ private String required = null; /** *

The filename of the template.

*/ private String template = null; /** *

True if trimming should occur.

*/ // FIXME: This info is only important at read-time, this probably should NOT exist private boolean trimming = true; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy