/* * 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.extensions.cdi.message.impl; import org.apache.myfaces.extensions.cdi.message.api.NamedArgument; import org.apache.myfaces.extensions.cdi.message.api.MessageContext; import org.apache.myfaces.extensions.cdi.message.impl.spi.ELProvider; import org.apache.myfaces.extensions.cdi.message.impl.spi.SimpleELContext; import javax.el.ExpressionFactory; import javax.el.ValueExpression; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Manfred Geiler * @author Gerhard Petracek */ public class ELAwareMessageInterpolator extends AbstractFormatterAwareMessageInterpolator { private static final long serialVersionUID = 3451979493272628741L; private static final Pattern MESSAGE_ARGS_PATTERN = Pattern.compile("\\{([^\\}]+?)\\}"); private ELProvider elProvider; public ELAwareMessageInterpolator(ELProvider elProvider) { this.elProvider = elProvider; } public String interpolate(MessageContext messageContext, String messageDescriptor, Serializable... arguments) { List<NamedArgument> namedArguments = addNamedArguments(arguments); if (namedArguments.size() > 0) { return interpolateNamedArguments(messageContext, messageDescriptor, namedArguments); } return messageDescriptor; } private List<NamedArgument> addNamedArguments(Serializable[] arguments) { List<NamedArgument> result = new ArrayList<NamedArgument>(); for (Serializable argument : arguments) { if (argument instanceof NamedArgument) { result.add((NamedArgument) argument); } } return result; } //TODO add warning for unused arguments,... private synchronized String interpolateNamedArguments(MessageContext messageContext, String messageDescriptor, List<NamedArgument> namedArguments) { ExpressionFactory factory = this.elProvider.createExpressionFactory(); SimpleELContext elContext = this.elProvider.createELContext(this.elProvider.createELResolver()); for (NamedArgument argument : namedArguments) { Serializable value = argument.getValue(); Class valueType = value != null ? value.getClass() : Object.class; elContext.setVariable(argument.getName(), factory.createValueExpression(value, valueType)); } Matcher matcher = MESSAGE_ARGS_PATTERN.matcher(messageDescriptor); StringBuffer buffer = new StringBuffer(); while (matcher.find()) { String resolvedArgumentValue; String expression = matcher.group(1); ValueExpression valueExpression = factory.createValueExpression(elContext, "${" + expression + "}", Object.class); Object value = valueExpression.getValue(elContext); if (value != null && !isUnresolvedArgument(expression, value)) { resolvedArgumentValue = formatAsString(messageContext, value).toString(); } else { resolvedArgumentValue = '{' + expression + '}'; //resolvedArgumentValue = ""; //TODO can we use it as alternative? } matcher.appendReplacement(buffer, resolvedArgumentValue); } matcher.appendTail(buffer); return buffer.toString(); } private boolean isUnresolvedArgument(String expression, Object value) { return value instanceof Long && expression.equals(value.toString()); } }