org.primefaces.util.ComponentUtils Maven / Gradle / Ivy
Show all versions of primefaces Show documentation
/**
* Copyright 2009-2018 PrimeTek.
*
* Licensed 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.primefaces.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.FacesWrapper;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.application.NavigationCase;
import javax.faces.application.ResourceHandler;
import javax.faces.component.*;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.render.Renderer;
import org.primefaces.component.api.RTLAware;
import org.primefaces.component.api.Widget;
import org.primefaces.config.PrimeConfiguration;
import org.primefaces.context.RequestContext;
import org.primefaces.expression.SearchExpressionUtils;
public class ComponentUtils {
public static final EnumSet VISIT_HINTS_SKIP_UNRENDERED = EnumSet.of(VisitHint.SKIP_UNRENDERED);
public static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
private static final String SB_ESCAPE = ComponentUtils.class.getName() + "#escape";
// marker for a undefined value when a null check is not reliable enough
private static final Object UNDEFINED_VALUE = new Object();
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("(\r\n|\n\r|\r|\n)");
public static String getValueToRender(FacesContext context, UIComponent component) {
return getValueToRender(context, component, UNDEFINED_VALUE);
}
/**
* Algorithm works as follows;
* - If it's an input component, submitted value is checked first since it'd be the value to be used in case validation errors
* terminates jsf lifecycle
* - Finally the value of the component is retrieved from backing bean and if there's a converter, converted value is returned
*
* @param context FacesContext instance
* @param component UIComponent instance whose value will be returned
* @param value The value of UIComponent if already evaluated outside. E.g. in the renderer.
* @return End text
*/
public static String getValueToRender(FacesContext context, UIComponent component, Object value) {
if (component instanceof ValueHolder) {
if (component instanceof EditableValueHolder) {
EditableValueHolder input = (EditableValueHolder) component;
Object submittedValue = input.getSubmittedValue();
PrimeConfiguration config = RequestContext.getCurrentInstance(context).getApplicationContext().getConfig();
if (config.isInterpretEmptyStringAsNull()
&& submittedValue == null
&& !input.isLocalValueSet()
&& context.isValidationFailed()
&& !input.isValid()) {
return null;
}
else if (submittedValue != null) {
return submittedValue.toString();
}
}
ValueHolder valueHolder = (ValueHolder) component;
if (value == UNDEFINED_VALUE) {
value = valueHolder.getValue();
}
//format the value as string
if (value != null) {
Converter converter = valueHolder.getConverter();
if (converter == null) {
Class valueType = value.getClass();
if (valueType == String.class
&& !RequestContext.getCurrentInstance(context).getApplicationContext().getConfig().isStringConverterAvailable()) {
return (String) value;
}
converter = context.getApplication().createConverter(valueType);
}
if (converter != null) {
return converter.getAsString(context, component, value);
}
else {
return value.toString(); //Use toString as a fallback if there is no explicit or implicit converter
}
}
else {
//component is a value holder but has no value
return null;
}
}
//component it not a value holder
return null;
}
/**
* Finds appropriate converter for a given value holder
*
* @param context FacesContext instance
* @param component ValueHolder instance to look converter for
* @return Converter
*/
public static Converter getConverter(FacesContext context, UIComponent component) {
if (!(component instanceof ValueHolder)) {
return null;
}
Converter converter = ((ValueHolder) component).getConverter();
if (converter != null) {
return converter;
}
ValueExpression valueExpression = component.getValueExpression("value");
if (valueExpression == null) {
return null;
}
Class converterType = valueExpression.getType(context.getELContext());
if (converterType == null || converterType == Object.class) {
// no conversion is needed
return null;
}
if (converterType == String.class
&& !RequestContext.getCurrentInstance(context).getApplicationContext().getConfig().isStringConverterAvailable()) {
return null;
}
return context.getApplication().createConverter(converterType);
}
// used by p:component - don't remove!
@Deprecated
public static String findComponentClientId(String id) {
FacesContext facesContext = FacesContext.getCurrentInstance();
UIComponent component = ComponentTraversalUtils.firstWithId(id, facesContext.getViewRoot());
return component.getClientId(facesContext);
}
public static String escapeSelector(String selector) {
return selector.replaceAll(":", "\\\\\\\\:");
}
@Deprecated
public static String resolveWidgetVar(String expression) {
return resolveWidgetVar(expression, FacesContext.getCurrentInstance().getViewRoot());
}
@Deprecated
public static String resolveWidgetVar(String expression, UIComponent component) {
return SearchExpressionUtils.resolveWidgetVar(expression, component);
}
public static boolean isValueBlank(String value) {
if (value == null) {
return true;
}
return value.trim().equals("");
}
public static boolean isRTL(FacesContext context, RTLAware component) {
boolean globalValue = RequestContext.getCurrentInstance(context).isRTL();
return globalValue || component.isRTL();
}
public static void processDecodesOfFacetsAndChilds(UIComponent component, FacesContext context) {
if (component.getFacetCount() > 0) {
for (UIComponent facet : component.getFacets().values()) {
facet.processDecodes(context);
}
}
if (component.getChildCount() > 0) {
for (int i = 0, childCount = component.getChildCount(); i < childCount; i++) {
UIComponent child = component.getChildren().get(i);
child.processDecodes(context);
}
}
}
public static void processValidatorsOfFacetsAndChilds(UIComponent component, FacesContext context) {
if (component.getFacetCount() > 0) {
for (UIComponent facet : component.getFacets().values()) {
facet.processValidators(context);
}
}
if (component.getChildCount() > 0) {
for (int i = 0, childCount = component.getChildCount(); i < childCount; i++) {
UIComponent child = component.getChildren().get(i);
child.processValidators(context);
}
}
}
public static void processUpdatesOfFacetsAndChilds(UIComponent component, FacesContext context) {
if (component.getFacetCount() > 0) {
for (UIComponent facet : component.getFacets().values()) {
facet.processUpdates(context);
}
}
if (component.getChildCount() > 0) {
for (int i = 0, childCount = component.getChildCount(); i < childCount; i++) {
UIComponent child = component.getChildren().get(i);
child.processUpdates(context);
}
}
}
public static NavigationCase findNavigationCase(FacesContext context, String outcome) {
ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
String outcomeValue = (outcome == null) ? context.getViewRoot().getViewId() : outcome;
return navHandler.getNavigationCase(context, null, outcomeValue);
}
public static Map> getUIParams(UIComponent component) {
List children = component.getChildren();
Map> params = null;
if (children != null && children.size() > 0) {
params = new LinkedHashMap>();
for (UIComponent child : children) {
if (child.isRendered() && (child instanceof UIParameter)) {
UIParameter uiParam = (UIParameter) child;
if (!uiParam.isDisable()) {
List paramValues = params.get(uiParam.getName());
if (paramValues == null) {
paramValues = new ArrayList();
params.put(uiParam.getName(), paramValues);
}
paramValues.add(String.valueOf(uiParam.getValue()));
}
}
}
}
return params;
}
public static String getResourceURL(FacesContext context, String value) {
if (isValueBlank(value)) {
return Constants.EMPTY_STRING;
}
else if (value.contains(ResourceHandler.RESOURCE_IDENTIFIER)) {
return value;
}
else {
String url = context.getApplication().getViewHandler().getResourceURL(context, value);
return context.getExternalContext().encodeResourceURL(url);
}
}
public static boolean isSkipIteration(VisitContext visitContext, FacesContext context) {
if (RequestContext.getCurrentInstance(context).getApplicationContext().getConfig().isAtLeastJSF21()) {
return visitContext.getHints().contains(VisitHint.SKIP_ITERATION);
}
else {
Boolean skipIterationHint = (Boolean) visitContext.getFacesContext().getAttributes().get(SKIP_ITERATION_HINT);
return skipIterationHint != null && skipIterationHint.booleanValue() == true;
}
}
public static String resolveWidgetVar(FacesContext context, Widget widget) {
UIComponent component = (UIComponent) widget;
String userWidgetVar = (String) component.getAttributes().get("widgetVar");
if (!isValueBlank(userWidgetVar)) {
return userWidgetVar;
}
else {
return "widget_" + component.getClientId(context).replaceAll("-|" + UINamingContainer.getSeparatorChar(context), "_");
}
}
public static String replaceNewLineWithHtml(String text) {
if (text == null) {
return null;
}
Matcher match = PATTERN_NEW_LINE.matcher(text);
if (match.find()) {
return match.replaceAll("
");
}
return text;
}
/**
* Duplicate code from json-simple project under apache license
* http://code.google.com/p/json-simple/source/browse/trunk/src/org/json/simple/JSONValue.java
*/
public static String escapeText(String text) {
if (text == null) {
return null;
}
StringBuilder sb = SharedStringBuilder.get(SB_ESCAPE);
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
//Reference: http://www.unicode.org/versions/Unicode5.1.0/
if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) {
String ss = Integer.toHexString(ch);
sb.append("\\u");
for (int k = 0; k < 4 - ss.length(); k++) {
sb.append('0');
}
sb.append(ss.toUpperCase());
}
else {
sb.append(ch);
}
}
}
return sb.toString();
}
public static String escapeEcmaScriptText(String text) {
if (text == null) {
return null;
}
StringBuilder sb = SharedStringBuilder.get(SB_ESCAPE);
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case '"':
sb.append("\\\"");
break;
case '\'':
sb.append("\\'");
break;
case '\\':
sb.append("\\\\");
break;
case '/':
sb.append("\\/");
break;
default:
sb.append(ch);
break;
}
}
return sb.toString();
}
/**
* Replace special characters with XML escapes:
*
* & (ampersand) is replaced by &
* < (less than) is replaced by <
* > (greater than) is replaced by >
* " (double quote) is replaced by "
*
*
* @param string The string to be escaped.
* @return The escaped string.
*/
public static String escapeXml(String string) {
StringBuilder sb = SharedStringBuilder.get(SB_ESCAPE, string.length());
for (int i = 0, length = string.length(); i < length; i++) {
char c = string.charAt(i);
switch (c) {
case '&':
sb.append("&");
break;
case '<':
sb.append("<");
break;
case '>':
sb.append(">");
break;
case '\'':
sb.append("'");
break;
default:
sb.append(c);
}
}
return sb.toString();
}
/**
* Use {@link ComponentTraversalUtils#closestForm(javax.faces.context.FacesContext, javax.faces.component.UIComponent)} instead.
*
* @param context
* @param component
* @return
* @deprecated
*/
@Deprecated
public static UIComponent findParentForm(FacesContext context, UIComponent component) {
return ComponentTraversalUtils.closestForm(context, component);
}
/**
* Gets a {@link TimeZone} instance by the parameter "timeZone" which can be String or {@link TimeZone} or null.
*
* @param timeZone given time zone
* @return resolved TimeZone
*/
public static TimeZone resolveTimeZone(Object timeZone) {
if (timeZone instanceof String) {
return TimeZone.getTimeZone((String) timeZone);
}
else if (timeZone instanceof TimeZone) {
return (TimeZone) timeZone;
}
else {
return TimeZone.getDefault();
}
}
public static T getUnwrappedRenderer(FacesContext context, String family, String rendererType, Class rendererClass) {
Renderer renderer = context.getRenderKit().getRenderer(family, rendererType);
while (renderer instanceof FacesWrapper) {
renderer = (Renderer) ((FacesWrapper) renderer).getWrapped();
}
return (T) renderer;
}
/**
* Calculates the current viewId - we can't get it from the ViewRoot if it's not available.
*
* @param context The {@link FacesContext}.
* @return The current viewId.
*/
public static String calculateViewId(FacesContext context) {
Map requestMap = context.getExternalContext().getRequestMap();
String viewId = (String) requestMap.get("javax.servlet.include.path_info");
if (viewId == null) {
viewId = context.getExternalContext().getRequestPathInfo();
}
if (viewId == null) {
viewId = (String) requestMap.get("javax.servlet.include.servlet_path");
}
if (viewId == null) {
viewId = context.getExternalContext().getRequestServletPath();
}
return viewId;
}
/**
* Duplicate code from OmniFacew project under apache license:
* https://github.com/omnifaces/omnifaces/blob/develop/license.txt
*
* URI-encode the given string using UTF-8. URIs (paths and filenames) have different encoding rules as compared to
* URL query string parameters. {@link URLEncoder} is actually only for www (HTML) form based query string parameter
* values (as used when a webbrowser submits a HTML form). URI encoding has a lot in common with URL encoding, but
* the space has to be %20 and some chars doesn't necessarily need to be encoded.
* @param string The string to be URI-encoded using UTF-8.
* @return The given string, URI-encoded using UTF-8, or null
if null
was given.
* @throws UnsupportedEncodingException if UTF-8 is not supported
*/
public static String encodeURI(String string) throws UnsupportedEncodingException {
if (string == null) {
return null;
}
return URLEncoder.encode(string, "UTF-8")
.replace("+", "%20")
.replace("%21", "!")
.replace("%27", "'")
.replace("%28", "(")
.replace("%29", ")")
.replace("%7E", "~");
}
/**
* Creates an RFC 6266 Content-Dispostion header following all UTF-8 conventions.
*
* @param value e.g. "attachment"
* @param filename the name of the file
* @return a valid Content-Disposition header in UTF-8 format
*/
public static String createContentDisposition(String value, String filename) {
try {
return String.format("%s;filename=\"%2$s\"; filename*=UTF-8''%2$s", value, encodeURI(filename));
}
catch (UnsupportedEncodingException e) {
throw new FacesException(e);
}
}
public static boolean isRequestSource(UIComponent component, FacesContext context) {
return component.getClientId(context).equals(context.getExternalContext().getRequestParameterMap().get(Constants.RequestParams.PARTIAL_SOURCE_PARAM));
}
/**
* Checks if the facet and one of the first level child's is rendered.
* @param facet The Facet component to check
* @return true when facet and one of the first level child's is rendered.
*/
public static boolean shouldRenderFacet(UIComponent facet) {
if (!facet.isRendered()) {
// For any future version of JSF where the f:facet gets a rendered attribute (https://github.com/javaserverfaces/mojarra/issues/4299)
// or there is only 1 child.
return false;
}
// Facet contains only 1 child, which is rendered due to previous test.
if (facet.getChildren().isEmpty()) {
return true;
}
for (int i = 0; i < facet.getChildren().size(); i++) {
// Stop when a child who is rendered is found.
if (facet.getChildren().get(i).isRendered()) {
return true;
}
}
return false;
}
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
}