From d0079c60583fdf3f6dfa4d82a238fbc8545cf188 Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sat, 13 Jun 2009 17:18:12 +0000 Subject: [PATCH] el-based message resolution; expected failure right now --- .../ui/message/DefaultMessageResolver.java | 92 +++++++++++-- .../ui/message/MessageBuilder.java | 70 +++++----- .../message/MessageResolutionException.java | 9 ++ .../ui/message/MessageBuilderTests.java | 10 +- .../ui/message/MockMessageSource.java | 48 +++++++ .../expression/Expression.java | 49 ++++--- .../expression/ParserContext.java | 25 +++- .../common/TemplateParserContext.java | 8 +- .../expression/spel/SpelExpression.java | 127 +++++++----------- 9 files changed, 284 insertions(+), 154 deletions(-) create mode 100644 org.springframework.context/src/main/java/org/springframework/ui/message/MessageResolutionException.java create mode 100644 org.springframework.context/src/test/java/org/springframework/ui/message/MockMessageSource.java diff --git a/org.springframework.context/src/main/java/org/springframework/ui/message/DefaultMessageResolver.java b/org.springframework.context/src/main/java/org/springframework/ui/message/DefaultMessageResolver.java index 016de967838..b79f3d3f2d1 100644 --- a/org.springframework.context/src/main/java/org/springframework/ui/message/DefaultMessageResolver.java +++ b/org.springframework.context/src/main/java/org/springframework/ui/message/DefaultMessageResolver.java @@ -16,10 +16,22 @@ package org.springframework.ui.message; import java.util.Locale; +import java.util.Map; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.expression.MapAccessor; import org.springframework.core.style.ToStringCreator; +import org.springframework.expression.AccessException; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.EvaluationException; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.ParseException; +import org.springframework.expression.ParserContext; +import org.springframework.expression.PropertyAccessor; +import org.springframework.expression.TypedValue; +import org.springframework.expression.spel.support.StandardEvaluationContext; class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable { @@ -27,22 +39,41 @@ class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable private String[] codes; - private Object[] args; - + private Map args; + private String defaultText; - public DefaultMessageResolver(Severity severity, String[] codes, Object[] args, String defaultText) { + private ExpressionParser expressionParser; + + public DefaultMessageResolver(Severity severity, String[] codes, Map args, + String defaultText, ExpressionParser expressionParser) { this.severity = severity; this.codes = codes; this.args = args; this.defaultText = defaultText; + this.expressionParser = expressionParser; } - + // implementing MessageResolver public Message resolveMessage(MessageSource messageSource, Locale locale) { - String text = messageSource.getMessage(this, locale); - return new TextMessage(severity, text); + String messageString = messageSource.getMessage(this, locale); + Expression message; + try { + message = expressionParser.parseExpression(messageString, ParserContext.TEMPLATE_EXPRESSION); + } catch (ParseException e) { + throw new MessageResolutionException("Failed to parse message expression", e); + } + try { + StandardEvaluationContext context = new StandardEvaluationContext(); + context.setRootObject(args); + context.addPropertyAccessor(new MapAccessor()); + context.addPropertyAccessor(new MessageSourceResolvableAccessor(messageSource, locale)); + String text = (String) message.getValue(context); + return new TextMessage(severity, text); + } catch (EvaluationException e) { + throw new MessageResolutionException("Failed to evaluate expression to generate message text", e); + } } // implementing MessageSourceResolver @@ -52,7 +83,7 @@ class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable } public Object[] getArguments() { - return args; + return null; } public String getDefaultMessage() { @@ -60,20 +91,21 @@ class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable } public String toString() { - return new ToStringCreator(this).append("severity", severity).append("codes", codes).append("args", args).append("defaultText", defaultText).toString(); + return new ToStringCreator(this).append("severity", severity).append("codes", codes).append("defaultText", + defaultText).toString(); } - + static class TextMessage implements Message { private Severity severity; - + private String text; - + public TextMessage(Severity severity, String text) { this.severity = severity; this.text = text; } - + public Severity getSeverity() { return severity; } @@ -81,7 +113,41 @@ class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable public String getText() { return text; } + + } + + static class MessageSourceResolvableAccessor implements PropertyAccessor { + + private MessageSource messageSource; + + private Locale locale; + + public MessageSourceResolvableAccessor(MessageSource messageSource, Locale locale) { + this.messageSource = messageSource; + this.locale = locale; + } + + public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException { + return true; + } + + public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { + // TODO this does not get called when resolving MessageSourceResolvable variables; only when accessing properties on MessageSourceResolvable targets. + return new TypedValue(messageSource.getMessage((MessageSourceResolvable)target, locale)); + } + + public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { + return false; + } + + @SuppressWarnings("unchecked") + public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException { + throw new UnsupportedOperationException("Should not be called"); + } + + public Class[] getSpecificTargetClasses() { + return new Class[] { MessageSourceResolvable.class }; + } } - } \ No newline at end of file diff --git a/org.springframework.context/src/main/java/org/springframework/ui/message/MessageBuilder.java b/org.springframework.context/src/main/java/org/springframework/ui/message/MessageBuilder.java index 3e9e6215a4c..2394bddcc01 100644 --- a/org.springframework.context/src/main/java/org/springframework/ui/message/MessageBuilder.java +++ b/org.springframework.context/src/main/java/org/springframework/ui/message/MessageBuilder.java @@ -15,14 +15,18 @@ */ package org.springframework.ui.message; -import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.List; +import java.util.Map; import java.util.Set; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.expression.MapAccessor; import org.springframework.core.style.ToStringCreator; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; /** * A convenient builder for building {@link MessageResolver} objects programmatically. @@ -46,16 +50,18 @@ import org.springframework.core.style.ToStringCreator; */ public class MessageBuilder { + private Severity severity; + private Set codes = new LinkedHashSet(); - private Severity severity; - - private List args = new ArrayList(); + private Map args = new LinkedHashMap(); private String defaultText; + private ExpressionParser expressionParser = new SpelExpressionParser(); + /** - * Records the severity of the message. + * Set the severity of the message. * @return this, for fluent API usage */ public MessageBuilder severity(Severity severity) { @@ -64,8 +70,8 @@ public class MessageBuilder { } /** - * Records that the message being built should try and resolve its text using the code provided. - * Adds the code to the codes list. Successive calls to this method add additional codes. + * Add a message code to use to resolve the message text. + * Successive calls to this method add additional codes. * Codes are applied in the order they are added. * @param code the message code * @return this, for fluent API usage @@ -76,31 +82,31 @@ public class MessageBuilder { } /** - * Records that the message being built has a variable argument. - * Adds the arg to the args list. Successive calls to this method add additional args. - * Args are applied in the order they are added. - * @param arg the message argument value + * Add a message argument. + * Successive calls to this method add additional args. + * @param name the argument name + * @param value the argument value * @return this, for fluent API usage */ - public MessageBuilder arg(Object arg) { - args.add(arg); + public MessageBuilder arg(String name, Object value) { + args.put(name, value); return this; } /** - * Records that the message being built has a variable argument, whose display value is also {@link MessageSourceResolvable}. - * Adds the arg to the args list. Successive calls to this method add additional resolvable args. - * Args are applied in the order they are added. - * @param arg the resolvable message argument + * Add a message argument whose value is a resolvable message code. + * Successive calls to this method add additional resolvable arguements. + * @param name the argument name + * @param value the argument value * @return this, for fluent API usage */ - public MessageBuilder resolvableArg(Object arg) { - args.add(new ResolvableArgument(arg)); + public MessageBuilder resolvableArg(String name, Object value) { + args.put(name, new ResolvableArgumentValue(value)); return this; } /** - * Records the fallback text of the message being built. + * Set the fallback text for the message. * If the message has no codes, this will always be used as the text. * If the message has codes but none can be resolved, this will always be used as the text. * @param text the default text @@ -113,28 +119,28 @@ public class MessageBuilder { /** * Builds the message that will be resolved. - * Call after recording builder instructions. + * Call after recording all builder instructions. * @return the built message resolver + * @throws Illegal */ public MessageResolver build() { if (severity == null) { severity = Severity.INFO; } if (codes == null && defaultText == null) { - throw new IllegalArgumentException( + throw new IllegalStateException( "A message code or the message text is required to build this message resolver"); } String[] codesArray = (String[]) codes.toArray(new String[codes.size()]); - Object[] argsArray = args.toArray(new Object[args.size()]); - return new DefaultMessageResolver(severity, codesArray, argsArray, defaultText); + return new DefaultMessageResolver(severity, codesArray, args, defaultText, expressionParser); } - private static class ResolvableArgument implements MessageSourceResolvable { + static class ResolvableArgumentValue implements MessageSourceResolvable { - private Object arg; + private Object value; - public ResolvableArgument(Object arg) { - this.arg = arg; + public ResolvableArgumentValue(Object value) { + this.value = value; } public Object[] getArguments() { @@ -142,15 +148,15 @@ public class MessageBuilder { } public String[] getCodes() { - return new String[] { arg.toString() }; + return new String[] { value.toString() }; } public String getDefaultMessage() { - return arg.toString(); + return String.valueOf(value); } public String toString() { - return new ToStringCreator(this).append("arg", arg).toString(); + return new ToStringCreator(this).append("value", value).toString(); } } diff --git a/org.springframework.context/src/main/java/org/springframework/ui/message/MessageResolutionException.java b/org.springframework.context/src/main/java/org/springframework/ui/message/MessageResolutionException.java new file mode 100644 index 00000000000..a8a8d9c0973 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/ui/message/MessageResolutionException.java @@ -0,0 +1,9 @@ +package org.springframework.ui.message; + +public class MessageResolutionException extends RuntimeException { + + public MessageResolutionException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/org.springframework.context/src/test/java/org/springframework/ui/message/MessageBuilderTests.java b/org.springframework.context/src/test/java/org/springframework/ui/message/MessageBuilderTests.java index 96eb3bab0f7..7328e9e2ae1 100644 --- a/org.springframework.context/src/test/java/org/springframework/ui/message/MessageBuilderTests.java +++ b/org.springframework.context/src/test/java/org/springframework/ui/message/MessageBuilderTests.java @@ -5,17 +5,17 @@ import static org.junit.Assert.assertEquals; import java.util.Locale; import org.junit.Test; -import org.springframework.context.support.StaticMessageSource; public class MessageBuilderTests { + private MessageBuilder builder = new MessageBuilder(); @Test public void buildMessage() { - MessageResolver resolver = builder.severity(Severity.ERROR).code("invalidFormat").resolvableArg("mathForm.decimalField") - .arg("#,###.##").defaultText("Field must be in format #,###.##").build(); - StaticMessageSource messageSource = new StaticMessageSource(); - messageSource.addMessage("invalidFormat", Locale.US, "{0} must be in format {1}"); + MessageResolver resolver = builder.severity(Severity.ERROR).code("invalidFormat").resolvableArg("label", "mathForm.decimalField") + .arg("format", "#,###.##").defaultText("Field must be in format #,###.##").build(); + MockMessageSource messageSource = new MockMessageSource(); + messageSource.addMessage("invalidFormat", Locale.US, "#{label} must be in format #{format}"); messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field"); Message message = resolver.resolveMessage(messageSource, Locale.US); assertEquals(Severity.ERROR, message.getSeverity()); diff --git a/org.springframework.context/src/test/java/org/springframework/ui/message/MockMessageSource.java b/org.springframework.context/src/test/java/org/springframework/ui/message/MockMessageSource.java new file mode 100644 index 00000000000..6327bd1e500 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/ui/message/MockMessageSource.java @@ -0,0 +1,48 @@ +package org.springframework.ui.message; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.springframework.context.support.AbstractMessageSource; +import org.springframework.util.Assert; + +public class MockMessageSource extends AbstractMessageSource { + + /** Map from 'code + locale' keys to message Strings */ + private final Map messages = new HashMap(); + + @Override + protected MessageFormat resolveCode(String code, Locale locale) { + throw new IllegalStateException("Should not be called"); + } + + @Override + protected String resolveCodeWithoutArguments(String code, Locale locale) { + return this.messages.get(code + "_" + locale.toString()); + } + + /** + * Associate the given message with the given code. + * @param code the lookup code + * @param locale the locale that the message should be found within + * @param msg the message associated with this lookup code + */ + public void addMessage(String code, Locale locale, String msg) { + Assert.notNull(code, "Code must not be null"); + Assert.notNull(locale, "Locale must not be null"); + Assert.notNull(msg, "Message must not be null"); + this.messages.put(code + "_" + locale.toString(), msg); + if (logger.isDebugEnabled()) { + logger.debug("Added message [" + msg + "] for code [" + code + "] and Locale [" + locale + "]"); + } + } + + @Override + public String toString() { + return getClass().getName() + ": " + this.messages; + } + +} + diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/Expression.java b/org.springframework.expression/src/main/java/org/springframework/expression/Expression.java index 7f4f1fe54f8..e50d029d3d2 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/Expression.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/Expression.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.expression; import org.springframework.core.convert.TypeDescriptor; @@ -69,13 +68,13 @@ public interface Expression { public T getValue(EvaluationContext context, Class desiredResultType) throws EvaluationException; /** - * Set this expression in the provided context to the value provided. + * Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method using + * the default context. * - * @param context the context in which to set the value of the expression - * @param value the new value - * @throws EvaluationException if there is a problem during evaluation + * @return the most general type of value that can be set on this context + * @throws EvaluationException if there is a problem determining the type */ - public void setValue(EvaluationContext context, Object value) throws EvaluationException; + public Class getValueType() throws EvaluationException; /** * Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method for @@ -91,10 +90,10 @@ public interface Expression { * Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method using * the default context. * - * @return the most general type of value that can be set on this context + * @return a type descriptor for the most general type of value that can be set on this context * @throws EvaluationException if there is a problem determining the type */ - public Class getValueType() throws EvaluationException; + public TypeDescriptor getValueTypeDescriptor() throws EvaluationException; /** * Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method for @@ -106,23 +105,6 @@ public interface Expression { */ public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException; - /** - * Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method using - * the default context. - * - * @return a type descriptor for the most general type of value that can be set on this context - * @throws EvaluationException if there is a problem determining the type - */ - public TypeDescriptor getValueTypeDescriptor() throws EvaluationException; - - - /** - * Returns the original string used to create this expression, unmodified. - * - * @return the original expression string - */ - public String getExpressionString(); - /** * Determine if an expression can be written to, i.e. setValue() can be called. * @@ -131,4 +113,21 @@ public interface Expression { * @throws EvaluationException if there is a problem determining if it is writable */ public boolean isWritable(EvaluationContext context) throws EvaluationException; + + /** + * Set this expression in the provided context to the value provided. + * + * @param context the context in which to set the value of the expression + * @param value the new value + * @throws EvaluationException if there is a problem during evaluation + */ + public void setValue(EvaluationContext context, Object value) throws EvaluationException; + + /** + * Returns the original string used to create this expression, unmodified. + * + * @return the original expression string + */ + public String getExpressionString(); + } \ No newline at end of file diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/ParserContext.java b/org.springframework.expression/src/main/java/org/springframework/expression/ParserContext.java index 1ef0a5ca4b6..2a32bb3dde1 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/ParserContext.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/ParserContext.java @@ -31,8 +31,8 @@ public interface ParserContext { * *
 	 * 	   Some literal text
-	 *     Hello ${name.firstName}!
-	 *     ${3 + 4}
+	 *     Hello #{name.firstName}!
+	 *     #{3 + 4}
 	 * 
* * @return true if the expression is a template, false otherwise @@ -54,5 +54,26 @@ public interface ParserContext { * @return the suffix that identifies the end of an expression */ String getExpressionSuffix(); + + /** + * The default ParserContext implementation that enables template expression parsing mode. + * The expression prefix is #{ and the expression suffix is }. + * @see #isTemplate() + */ + public static final ParserContext TEMPLATE_EXPRESSION = new ParserContext() { + + public String getExpressionPrefix() { + return "#{"; + } + + public String getExpressionSuffix() { + return "}"; + } + + public boolean isTemplate() { + return true; + } + + }; } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/common/TemplateParserContext.java b/org.springframework.expression/src/main/java/org/springframework/expression/common/TemplateParserContext.java index 235b6f6a6d8..000dde7e0e5 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/common/TemplateParserContext.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/common/TemplateParserContext.java @@ -31,7 +31,13 @@ public class TemplateParserContext implements ParserContext { private final String expressionSuffix; - + /** + * Creates a new TemplateParserContext with the default #{ prefix and } suffix. + */ + public TemplateParserContext() { + this("#{", "}"); + } + /** * Create a new TemplateParserContext for the given prefix and suffix. * @param expressionPrefix the expression prefix to use diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelExpression.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelExpression.java index 6f7e49f31dc..c270a1861ed 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelExpression.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelExpression.java @@ -22,6 +22,7 @@ import org.springframework.expression.Expression; import org.springframework.expression.common.ExpressionUtils; import org.springframework.expression.spel.ast.SpelNodeImpl; import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.util.Assert; /** * A SpelExpressions represents a parsed (valid) expression that is ready to be evaluated in a specified context. An @@ -48,35 +49,27 @@ public class SpelExpression implements Expression { this.configuration = configuration; } - /** - * @return the expression string that was parsed to create this expression instance - */ - public String getExpressionString() { - return this.expression; - } - - /** - * {@inheritDoc} - */ + // implementing Expression + public Object getValue() throws EvaluationException { - ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext(),configuration); - return this.ast.getValue(expressionState); + ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext(), configuration); + return ast.getValue(expressionState); } - - /** - * {@inheritDoc} - */ + + public T getValue(Class expectedResultType) throws EvaluationException { + ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext(), configuration); + Object result = ast.getValue(expressionState); + return ExpressionUtils.convert(expressionState.getEvaluationContext(), result, expectedResultType); + } + public Object getValue(EvaluationContext context) throws EvaluationException { - return this.ast.getValue(new ExpressionState(context,configuration)); + Assert.notNull(context, "The EvaluationContext is required"); + return ast.getValue(new ExpressionState(context, configuration)); } - /** - * {@inheritDoc} - */ @SuppressWarnings("unchecked") public T getValue(EvaluationContext context, Class expectedResultType) throws EvaluationException { - Object result = ast.getValue(new ExpressionState(context,configuration)); - + Object result = ast.getValue(new ExpressionState(context, configuration)); if (result != null && expectedResultType != null) { Class resultType = result.getClass(); if (!expectedResultType.isAssignableFrom(resultType)) { @@ -87,25 +80,49 @@ public class SpelExpression implements Expression { return (T) result; } - /** - * {@inheritDoc} - */ - public void setValue(EvaluationContext context, Object value) throws EvaluationException { - this.ast.setValue(new ExpressionState(context,configuration), value); + public Class getValueType() throws EvaluationException { + return ast.getValueInternal(new ExpressionState(new StandardEvaluationContext(), configuration)).getTypeDescriptor().getType(); } - /** - * {@inheritDoc} - */ - public boolean isWritable(EvaluationContext context) throws EvaluationException { - return this.ast.isWritable(new ExpressionState(context,configuration)); + public Class getValueType(EvaluationContext context) throws EvaluationException { + Assert.notNull(context, "The EvaluationContext is required"); + ExpressionState eState = new ExpressionState(context, configuration); + TypeDescriptor typeDescriptor = ast.getValueInternal(eState).getTypeDescriptor(); + return typeDescriptor.getType(); } + public TypeDescriptor getValueTypeDescriptor() throws EvaluationException { + return ast.getValueInternal(new ExpressionState(new StandardEvaluationContext(), configuration)).getTypeDescriptor(); + } + + public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException { + Assert.notNull(context, "The EvaluationContext is required"); + ExpressionState eState = new ExpressionState(context, configuration); + TypeDescriptor typeDescriptor = ast.getValueInternal(eState).getTypeDescriptor(); + return typeDescriptor; + } + + public String getExpressionString() { + return expression; + } + + public boolean isWritable(EvaluationContext context) throws EvaluationException { + Assert.notNull(context, "The EvaluationContext is required"); + return ast.isWritable(new ExpressionState(context, configuration)); + } + + public void setValue(EvaluationContext context, Object value) throws EvaluationException { + Assert.notNull(context, "The EvaluationContext is required"); + ast.setValue(new ExpressionState(context, configuration), value); + } + + // impl only + /** * @return return the Abstract Syntax Tree for the expression */ public SpelNode getAST() { - return this.ast; + return ast; } /** @@ -116,49 +133,7 @@ public class SpelExpression implements Expression { * @return the string representation of the AST */ public String toStringAST() { - return this.ast.toStringAST(); - } - - /** - * {@inheritDoc} - */ - public Class getValueType(EvaluationContext context) throws EvaluationException { - ExpressionState eState = new ExpressionState(context,configuration); - TypeDescriptor typeDescriptor = this.ast.getValueInternal(eState).getTypeDescriptor(); - return typeDescriptor.getType(); - } - - /** - * {@inheritDoc} - */ - public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException { - ExpressionState eState = new ExpressionState(context,configuration); - TypeDescriptor typeDescriptor = this.ast.getValueInternal(eState).getTypeDescriptor(); - return typeDescriptor; - } - - /** - * {@inheritDoc} - */ - public Class getValueType() throws EvaluationException { - return this.ast.getValueInternal(new ExpressionState(new StandardEvaluationContext(),configuration)).getTypeDescriptor().getType(); - } - - /** - * {@inheritDoc} - */ - public TypeDescriptor getValueTypeDescriptor() throws EvaluationException { - return this.ast.getValueInternal(new ExpressionState(new StandardEvaluationContext(),configuration)).getTypeDescriptor(); - } - - - /** - * {@inheritDoc} - */ - public T getValue(Class expectedResultType) throws EvaluationException { - ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext(),configuration); - Object result = this.ast.getValue(expressionState); - return ExpressionUtils.convert(expressionState.getEvaluationContext(), result, expectedResultType); + return ast.toStringAST(); } }