blob: 5b5964de0392152d88b83dfbdef10d5cb843cdd4 [file] [log] [blame]
/*
* 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.core.api.shared;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import java.util.Collection;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
/**
* A collection of static helper methods for locating UIComponents.
*/
public class _ComponentUtils
{
public static final String V_ID_PREFIX = "__v_";
public static final String RD_ID_PREFIX = "__rd_";
public static final int UNIQUE_COMPONENT_V_IDS_SIZE = 50;
public static final int UNIQUE_COMPONENT_RD_IDS_SIZE = 50;
public static final String[] UNIQUE_COMPONENT_V_IDS;
public static final String[] UNIQUE_COMPONENT_RD_IDS;
static
{
String[] uniqueV = new String[UNIQUE_COMPONENT_V_IDS_SIZE];
String[] uniqueRD = new String[UNIQUE_COMPONENT_RD_IDS_SIZE];
StringBuilder bld = new StringBuilder(20);
for (int i = 0; i < UNIQUE_COMPONENT_V_IDS_SIZE; i++)
{
uniqueV[i] = bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append("__v_").append(i).toString();
bld.setLength(0);
}
for (int i = 0; i < UNIQUE_COMPONENT_RD_IDS_SIZE; i++)
{
uniqueRD[i] = bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append("__rd_").append(i).toString();
bld.setLength(0);
}
UNIQUE_COMPONENT_RD_IDS = uniqueRD;
UNIQUE_COMPONENT_V_IDS = uniqueV;
}
private _ComponentUtils()
{
}
public static UIComponent findParentNamingContainer(UIComponent component, boolean returnRootIfNotFound)
{
NamingContainer result = closest(NamingContainer.class, component);
if (result != null)
{
return (UIComponent) result;
}
if (returnRootIfNotFound)
{
return getRootComponent(component);
}
return null;
}
public static <T> T closest(Class<T> type, UIComponent base)
{
UIComponent parent = base.getParent();
while (parent != null)
{
if (type.isAssignableFrom(parent.getClass()))
{
return (T) parent;
}
parent = parent.getParent();
}
return null;
}
public static UIComponent getRootComponent(UIComponent component)
{
UIComponent parent;
for (;;)
{
parent = component.getParent();
if (parent == null)
{
return component;
}
component = parent;
}
}
/**
* Find the component with the specified id starting from the specified component.
* <p>
* Param id must not contain any NamingContainer.SEPARATOR_CHAR characters (ie ":"). This method explicitly does
* <i>not</i> search into any child naming container components; this is expected to be handled by the caller of
* this method.
* <p>
* For an implementation of findComponent which does descend into child naming components, see
* org.apache.myfaces.custom.util.ComponentUtils.
*
* @return findBase, a descendant of findBase, or null.
*/
public static UIComponent findComponent(UIComponent findBase, String id, final char separatorChar)
{
if (!(findBase instanceof NamingContainer) && id.equals(findBase.getId()))
{
return findBase;
}
int facetCount = findBase.getFacetCount();
if (facetCount > 0)
{
for (UIComponent facet : findBase.getFacets().values())
{
if (!(facet instanceof NamingContainer))
{
UIComponent find = findComponent(facet, id, separatorChar);
if (find != null)
{
return find;
}
}
else if (id.equals(facet.getId()))
{
return facet;
}
}
}
for (int i = 0, childCount = findBase.getChildCount(); i < childCount; i++)
{
UIComponent child = findBase.getChildren().get(i);
if (!(child instanceof NamingContainer))
{
UIComponent find = findComponent(child, id, separatorChar);
if (find != null)
{
return find;
}
}
else if (id.equals(child.getId()))
{
return child;
}
}
if (findBase instanceof NamingContainer && id.equals(findBase.getId()))
{
return findBase;
}
return null;
}
public static UIComponent findComponentChildOrFacetFrom(UIComponent parent, String id, String innerExpr)
{
if (parent.getFacetCount() > 0)
{
for (UIComponent facet : parent.getFacets().values())
{
if (id.equals(facet.getId()))
{
if (innerExpr == null)
{
return facet;
}
else if (facet instanceof NamingContainer)
{
UIComponent find = facet.findComponent(innerExpr);
if (find != null)
{
return find;
}
}
}
else if (!(facet instanceof NamingContainer))
{
UIComponent find = findComponentChildOrFacetFrom(facet, id, innerExpr);
if (find != null)
{
return find;
}
}
}
}
if (parent.getChildCount() > 0)
{
for (int i = 0, childCount = parent.getChildCount(); i < childCount; i++)
{
UIComponent child = parent.getChildren().get(i);
if (id.equals(child.getId()))
{
if (innerExpr == null)
{
return child;
}
else if (child instanceof NamingContainer)
{
UIComponent find = child.findComponent(innerExpr);
if (find != null)
{
return find;
}
}
}
else if (!(child instanceof NamingContainer))
{
UIComponent find = findComponentChildOrFacetFrom(child, id, innerExpr);
if (find != null)
{
return find;
}
}
}
}
return null;
}
public static void callValidators(FacesContext context, UIInput input, Object convertedValue)
{
// first invoke the list of validator components
Validator[] validators = input.getValidators();
for (int i = 0; i < validators.length; i++)
{
Validator validator = validators[i];
try
{
validator.validate(context, input, convertedValue);
}
catch (ValidatorException e)
{
input.setValid(false);
String validatorMessage = input.getValidatorMessage();
if (validatorMessage != null)
{
context.addMessage(input.getClientId(context),
new FacesMessage(FacesMessage.SEVERITY_ERROR, validatorMessage, validatorMessage));
}
else
{
FacesMessage facesMessage = e.getFacesMessage();
if (facesMessage != null)
{
context.addMessage(input.getClientId(context), facesMessage);
}
Collection<FacesMessage> facesMessages = e.getFacesMessages();
if (facesMessages != null)
{
for (FacesMessage message : facesMessages)
{
context.addMessage(input.getClientId(context), message);
}
}
}
}
}
}
public static String getPathToComponent(UIComponent component)
{
StringBuilder buf = new StringBuilder();
if (component == null)
{
buf.append("{Component-Path : ");
buf.append("[null]}");
return buf.toString();
}
getPathToComponent(component, buf);
buf.insert(0, "{Component-Path : ");
buf.append('}');
return buf.toString();
}
/**
* Call {@link UIComponent#pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent)},
* reads the isRendered property, call {@link
* UIComponent#popComponentFromEL} and returns the value of isRendered.
*/
public static boolean isRendered(FacesContext facesContext, UIComponent uiComponent)
{
// We must call pushComponentToEL here because ValueExpression may have
// implicit object "component" used.
try
{
uiComponent.pushComponentToEL(facesContext, uiComponent);
return uiComponent.isRendered();
}
finally
{
uiComponent.popComponentFromEL(facesContext);
}
}
public static void getPathToComponent(UIComponent component, StringBuilder buf)
{
if (component == null)
{
return;
}
StringBuilder intBuf = new StringBuilder();
intBuf.append("[Class: ");
intBuf.append(component.getClass().getName());
if (component instanceof UIViewRoot)
{
intBuf.append(",ViewId: ");
intBuf.append(((UIViewRoot)component).getViewId());
}
else
{
intBuf.append(",Id: ");
intBuf.append(component.getId());
}
intBuf.append(']');
buf.insert(0, intBuf.toString());
getPathToComponent(component.getParent(), buf);
}
}