org.apache.myfaces.view.facelets.el.CompositeComponentELUtils Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.myfaces.view.facelets.el;
import java.util.LinkedList;
import java.util.regex.Pattern;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.view.Location;
/**
* Utility class for composite components when used in EL Expressions --> #{cc}
*
* @author Jakob Korherr (latest modification by $Author: lu4242 $)
* @version $Revision: 965450 $ $Date: 2010-07-19 07:21:18 -0500 (Mon, 19 Jul 2010) $
*/
public final class CompositeComponentELUtils
{
/**
* The key under which the component stack is stored in the FacesContext.
* ATTENTION: this constant is duplicate in UIComponent.
*/
public static final String COMPONENT_STACK = "componentStack:" + UIComponent.class.getName();
/**
* The key under which the current composite component is stored in the attribute
* map of the FacesContext.
*/
public static final String CURRENT_COMPOSITE_COMPONENT_KEY = "org.apache.myfaces.compositecomponent.current";
/**
* The key under which the Location of the composite componente is stored
* in the attributes map of the component by InterfaceHandler.
*/
public static final String LOCATION_KEY = "org.apache.myfaces.compositecomponent.location";
/**
* A regular expression used to determine if cc is used in an expression String.
*/
public static final Pattern CC_EXPRESSION_REGEX = Pattern.compile(".*[^\\w\\.]cc[^\\w].*");
/**
* A regular expression used to determine if cc.attrs is used as a method expression
* in an expression String. This means cc.attrs must occur, must stand before a '(',
* because otherwise it would be a method parameter (EL 2.2), and there must be no '.' after
* cc.attrs unless there is a left parenthesis before it (e.g. #{cc.attrs.method(bean.parameter)}).
*
* Explanation of the parts:
* - [^\\(]* - There can be any character except a '(' before cc.attrs
* - [^\\w\\.\\(] - There must be no word character, dot, or left parenthesis directly before cc.attrs
* - cc\\.attrs\\. - "cc.attrs." must occur
* - [^\\.]* - There must be no dot after cc.attrs to indicate a method invocation on cc.attrs
* - (\\(.*)? - If there is a left paranthesis after cc.attrs, a dot is allowed again
*/
public static final Pattern CC_ATTRS_METHOD_EXPRESSION_REGEX = Pattern.compile("[^\\(]*[^\\w\\.\\(]cc\\.attrs\\.[^\\.]*(\\(.*)?");
/**
* private constructor
*/
private CompositeComponentELUtils()
{
// no instantiation of this class
}
/**
* Trys to find a composite component on the composite component stack
* and using UIComponent.getCurrentCompositeComponent() based on the
* location of the facelet page that generated the composite component.
* @param facesContext
* @param location
* @return
*/
public static UIComponent getCompositeComponentBasedOnLocation(FacesContext facesContext,
Location location)
{
// look on the component stack
LinkedList componentStack = getComponentStack(facesContext);
if (componentStack != null && !componentStack.isEmpty())
{
// try to find the right composite component
for (UIComponent component : componentStack)
{
if (UIComponent.isCompositeComponent(component))
{
Location componentLocation = (Location) component.getAttributes().get(LOCATION_KEY);
if (componentLocation != null
&& componentLocation.getPath().equals(location.getPath()))
{
return component;
}
}
}
}
// try to find it using UIComponent.getCurrentCompositeComponent()
UIComponent component = UIComponent.getCurrentCompositeComponent(facesContext);
while (component != null)
{
Location componentLocation = (Location) component.getAttributes().get(LOCATION_KEY);
if (componentLocation != null
&& componentLocation.getPath().equals(location.getPath()))
{
return component;
}
// get the composite component's parent
component = UIComponent.getCompositeComponentParent(component);
}
// not found
return null;
}
/**
* Gets the current component stack from the FacesContext.
* @param facesContext
* @return
*/
@SuppressWarnings("unchecked")
public static LinkedList getComponentStack(FacesContext facesContext)
{
return (LinkedList) facesContext.getAttributes().get(COMPONENT_STACK);
}
/**
* Trys to get the composite component using getCompositeComponentBasedOnLocation()
* and saves it in an attribute on the FacesContext, which is then used by
* CompositeComponentImplicitObject.
* @param facesContext
* @param location
*/
public static void saveCompositeComponentForResolver(FacesContext facesContext, Location location)
{
UIComponent cc = getCompositeComponentBasedOnLocation(facesContext, location);
facesContext.getAttributes().put(CURRENT_COMPOSITE_COMPONENT_KEY, cc);
}
/**
* Removes the composite component from the attribute map of the FacesContext.
* @param facesContext
*/
public static void removeCompositeComponentForResolver(FacesContext facesContext)
{
facesContext.getAttributes().remove(CURRENT_COMPOSITE_COMPONENT_KEY);
}
/**
* Tests if the expression refers to the current composite component: #{cc}
* @return
*/
public static boolean isCompositeComponentExpression(String expression)
{
return CC_EXPRESSION_REGEX.matcher(expression).matches();
}
/**
* Tests if cc.attrs is used as a method expression in an expression String. This means
* cc.attrs must occur, must stand before a '(', because otherwise it would be a method parameter
* (EL 2.2), and there must be no '.' after cc.attrs unless there is a left parenthesis
* before it (e.g. #{cc.attrs.method(bean.parameter)}).
* @param expression
* @return
*/
public static boolean isCompositeComponentAttrsMethodExpression(String expression)
{
return CC_ATTRS_METHOD_EXPRESSION_REGEX.matcher(expression).matches();
}
}