提交 6d03f881 编写于 作者: A Andy Clement

new files

上级 32bea88e
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel;
import org.springframework.expression.EvaluationException;
/**
* Represents a node in the Ast for a parsed expression.
*
* @author Andy Clement
*/
public interface SpelNode {
/**
* Evaluate the expression node in the context of the supplied expression state and return the value.
*
* @param expressionState the current expression state (includes the context)
* @return the value of this node evaluated against the specified state
*/
Object getValue(ExpressionState expressionState) throws EvaluationException;
/**
* Determine if this expression node will support a setValue() call.
*
* @param expressionState the current expression state (includes the context)
* @return true if the expression node will allow setValue()
* @throws EvaluationException if something went wrong trying to determine if the node supports writing
*/
boolean isWritable(ExpressionState expressionState) throws EvaluationException;
/**
* Evaluate the expression to a node and then set the new value on that node. For example, if the expression
* evaluates to a property reference then the property will be set to the new value.
*
* @param expressionState the current expression state (includes the context)
* @param newValue the new value
* @throws EvaluationException if any problem occurs evaluating the expression or setting the new value
*/
void setValue(ExpressionState expressionState, Object newValue) throws EvaluationException;
/**
* @return the string form of this AST node
*/
String toStringAST();
/**
* @return the number of children under this node
*/
int getChildCount();
/**
* Helper method that returns a SpelNode rather than an Antlr Tree node.
*
* @return the child node cast to a SpelNode
*/
SpelNode getChild(int index);
/**
* Determine the class of the object passed in, unless it is already a class object.
*
* @param o the object that the caller wants the class of
* @return the class of the object if it is not already a class object, or null if the object is null
*/
Class<?> getObjectClass(Object o);
/**
* @return the start position of this Ast node in the expression string
*/
public int getStartPosition();
}
\ No newline at end of file
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel;
/**
* Wrap a checked SpelException temporarily so that it can be passed through some infrastructure code
* (for example Antlr) before being unwrapped at the top level.
*
* @author Andy Clement
*/
public class WrappedELException extends RuntimeException {
public WrappedELException(SpelException e) {
super(e);
}
@Override
public SpelException getCause() {
return (SpelException) super.getCause();
}
}
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel.antlr;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.SpelException;
import org.springframework.expression.spel.SpelExpression;
import org.springframework.expression.spel.SpelNode;
import org.springframework.expression.spel.WrappedELException;
import org.springframework.expression.spel.SpelExpressionParser.SpelInternalParser;
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
import org.springframework.expression.spel.generated.SpringExpressionsParser.expr_return;
/**
* Wrap an Antlr lexer and parser.
*
* @author Andy Clement
*/
public class SpelAntlrExpressionParser implements SpelInternalParser {
private final SpringExpressionsLexer lexer;
private final SpringExpressionsParserExtender parser;
public SpelAntlrExpressionParser() {
lexer = new SpringExpressionsLexerExtender();
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new SpringExpressionsParserExtender(tokens);
}
/**
* Parse an expression string.
*
* @param expressionString the expression to parse
* @param context the parser context in which to perform the parse
* @return a parsed expression object
* @throws ParseException if the expression is invalid
*/
public Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
try {
lexer.setCharStream(new ANTLRStringStream(expressionString));
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser.setTokenStream(tokens);
expr_return exprReturn = parser.expr();
SpelExpression newExpression = new SpelExpression(expressionString, (SpelNode) exprReturn.getTree());
return newExpression;
} catch (RecognitionException re) {
ParseException exception = new ParseException(expressionString, "Recognition error at position: "
+ re.charPositionInLine + ": " + re.getMessage(), re);
throw exception;
} catch (WrappedELException e) {
SpelException wrappedException = e.getCause();
throw new ParseException(expressionString, "Parsing problem: " + wrappedException.getMessage(),
wrappedException);
}
}
}
\ No newline at end of file
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel.antlr;
import org.antlr.runtime.RecognitionException;
import org.springframework.expression.spel.SpelException;
import org.springframework.expression.spel.SpelMessages;
import org.springframework.expression.spel.WrappedELException;
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
public class SpringExpressionsLexerExtender extends SpringExpressionsLexer {
public SpringExpressionsLexerExtender() {
super();
}
/**
* recover() attempts to provide better error messages once something has gone wrong. It then throws a
* InternalELException (has to be this unchecked exception as the exception must flow through Antlr lexer methods
* that do not have declared exceptions). The InternalELException will be caught at the top level and altered to
* include context (line,column) information before being rethrown.<br>
*
* This error analysis code is in recover() rather than reportError() because reportError() isn't always called by
* the lexer and there is no way to add the calls to it by editing the .g file.
*/
@Override
public void recover(RecognitionException re) {
// TODO recovery needs an overhaul once the expression language syntax is agreed
// List<?> rules = getRuleInvocationStack(re, SpringExpressionsLexer.class.getName());
// String failedRule = (String) rules.get(rules.size() - 1);
// System.out.println("DBG: lexer rule " + failedRule);
// need a concrete example of error recovery in here please! then i can delete the below
// if (re instanceof NoViableAltException) {
// NoViableAltException nvae = (NoViableAltException) re;
// // example error data: { "abc": def }
// if (failedRule.equals("mTokens") && Character.isLetter((char) (nvae.getUnexpectedType()))) {
// logger.error(ParserMessage.ERROR_STRINGS_MUST_BE_QUOTED, re.line, re.charPositionInLine);
// }
//
// } else if (re instanceof MismatchedRangeException) {
// // MismatchedRangeException mre = (MismatchedRangeException) re;
// // example error data: [ 123e ]
// if (failedRule.equals("mDIGIT") && rules.size() > 3 && ((String) rules.get(rules.size() -
// 3)).equals("mExponent")) {
// logger.error(ParserMessage.ERROR_INVALID_EXPONENT, re.line, re.charPositionInLine);
// }
// } else if (re instanceof MismatchedTokenException) {
// MismatchedTokenException mte = (MismatchedTokenException) re;
// logger.error(ParserMessage.ERROR_MISMATCHED_CHARACTER, mte.charPositionInLine, mte.charPositionInLine,
// getCharErrorDisplay(mte.expecting), getCharErrorDisplay(mte.c));
// }
SpelException realException = new SpelException(re, SpelMessages.RECOGNITION_ERROR, re.toString());
throw new WrappedELException(realException);
}
@Override
public void reportError(RecognitionException re) {
// Do not report anything. If better messages could be reported they will have been reported
// by the recover() method above.
}
// private String getTokenForId(int id) {
// if (id == -1)
// return "EOF";
// return getTokenNames()[id];
// }
}
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel.antlr;
import org.antlr.runtime.BitSet;
import org.antlr.runtime.IntStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenStream;
import org.springframework.expression.spel.SpelException;
import org.springframework.expression.spel.SpelMessages;
import org.springframework.expression.spel.WrappedELException;
import org.springframework.expression.spel.ast.SpelTreeAdaptor;
import org.springframework.expression.spel.generated.SpringExpressionsParser;
public class SpringExpressionsParserExtender extends SpringExpressionsParser {
public SpringExpressionsParserExtender(TokenStream input) {
super(input);
setTreeAdaptor(new SpelTreeAdaptor());
}
/**
* Override super type implementation and just include the character position rather than the line number since the
* expressions are nearly all going to be just one line.
*/
@Override
public String getErrorHeader(RecognitionException e) {
StringBuilder retval = new StringBuilder();
retval.append("(pos ").append(e.charPositionInLine).append("): ");
return retval.toString();
}
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
String message = getErrorMessage(e, tokenNames);
// TODO would something like this be worthwhile to improve messages?
// if (message.equals("no viable alternative at input '<EOF>'") && !paraphrase.isEmpty()) {
// // This means we ran out of input building something, that something is named in paraphrase
// message = "no more input data to process whilst constructing " + paraphrase.peek();
// }
SpelException parsingProblem = new SpelException(e.charPositionInLine, e, SpelMessages.PARSE_PROBLEM, message);
throw new WrappedELException(parsingProblem);
}
/**
* Overridden purely because the base implementation does a System.err.println()
*/
@Override
public void recoverFromMismatchedToken(IntStream input, RecognitionException e, int ttype, BitSet follow)
throws RecognitionException {
// if next token is what we are looking for then "delete" this token
if (input.LA(2) == ttype) {
reportError(e);
/*
* System.err.println("recoverFromMismatchedToken deleting "+input.LT(1)+ " since "+input.LT(2)+" is what we
* want");
*/
beginResync();
input.consume(); // simply delete extra token
endResync();
input.consume(); // move past ttype token as if all were ok
return;
}
if (!recoverFromMismatchedElement(input, e, follow)) {
throw e;
}
}
@Override
public String getTokenErrorDisplay(Token t) {
if (t == null) {
return "<unknown>";
}
return super.getTokenErrorDisplay(t);
}
}
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel.ast;
import org.antlr.runtime.Token;
import org.springframework.expression.spel.SpelException;
import org.springframework.expression.spel.ExpressionState;
public class EmptySpelNode extends SpelNodeImpl {
public EmptySpelNode(Token payload) {
super(payload);
}
@Override
public Object getValueInternal(ExpressionState state) throws SpelException {
throw new RuntimeException("?");
}
@Override
public String toStringAST() {
return "<no string form node '" + getTokenName() + "'>";
}
}
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel.ast;
import java.io.Serializable;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.common.ExpressionUtils;
import org.springframework.expression.spel.ExpressionState;
import org.springframework.expression.spel.SpelNode;
import org.springframework.expression.spel.SpelException;
import org.springframework.expression.spel.SpelMessages;
import org.springframework.expression.spel.generated.SpringExpressionsParser;
import org.springframework.expression.spel.standard.StandardEvaluationContext;
/**
* The common supertype of all AST nodes in a parsed Spring Expression Language format expression.
*
* @author Andy Clement
*
*/
public abstract class SpelNodeImpl extends CommonTree implements Serializable, SpelNode {
/**
* The Antlr parser uses this constructor to build SpelNodes.
*
* @param payload the token for the node that has been parsed
*/
protected SpelNodeImpl(Token payload) {
super(payload);
}
public final Object getValue(ExpressionState expressionState) throws EvaluationException {
if (expressionState==null) {
return getValue(new ExpressionState(new StandardEvaluationContext()));
} else {
return getValueInternal(expressionState);
}
}
/* (non-Javadoc)
* @see org.springframework.expression.spel.ast.ISpelNode#getValue(org.springframework.expression.spel.ExpressionState)
*/
public abstract Object getValueInternal(ExpressionState expressionState) throws EvaluationException;
/* (non-Javadoc)
* @see org.springframework.expression.spel.ast.ISpelNode#isWritable(org.springframework.expression.spel.ExpressionState)
*/
public boolean isWritable(ExpressionState expressionState) throws EvaluationException {
return false;
}
/* (non-Javadoc)
* @see org.springframework.expression.spel.ast.ISpelNode#setValue(org.springframework.expression.spel.ExpressionState, java.lang.Object)
*/
public void setValue(ExpressionState expressionState, Object newValue) throws EvaluationException {
throw new SpelException(getCharPositionInLine(), SpelMessages.SETVALUE_NOT_SUPPORTED, getClass(),
getTokenName());
}
/**
* @return return the token this node represents
*/
protected String getTokenName() {
if (getToken() == null) {
return "UNKNOWN";
}
return SpringExpressionsParser.tokenNames[getToken().getType()];
}
/* (non-Javadoc)
* @see org.springframework.expression.spel.ast.ISpelNode#toStringAST()
*/
public abstract String toStringAST();
/* (non-Javadoc)
* @see org.springframework.expression.spel.ast.ISpelNode#getChild(int)
*/
@Override
public SpelNodeImpl getChild(int index) {
return (SpelNodeImpl) super.getChild(index);
}
/* (non-Javadoc)
* @see org.springframework.expression.spel.ast.ISpelNode#getObjectClass(java.lang.Object)
*/
public Class<?> getObjectClass(Object o) {
if (o == null)
return null;
return (o instanceof Class) ? ((Class<?>) o) : o.getClass();
}
protected final Object getValue(ExpressionState state, Class<?> desiredReturnType) throws EvaluationException {
Object result = getValueInternal(state);
if (result != null && desiredReturnType != null) {
Class<?> resultType = result.getClass();
if (desiredReturnType.isAssignableFrom(resultType)) {
return result;
}
// Attempt conversion to the requested type, may throw an exception
return ExpressionUtils.convert(state.getEvaluationContext(), result, desiredReturnType);
}
return result;
}
public int getStartPosition() {
return getCharPositionInLine();
}
}
/*
* Copyright 2004-2008 the original author or authors.
*
* 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.springframework.expression.spel.ast;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTreeAdaptor;
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
public class SpelTreeAdaptor extends CommonTreeAdaptor {
@Override
public Object create(Token payload) {
if (payload != null) {
switch (payload.getType()) {
case SpringExpressionsLexer.TRUE:
return new BooleanLiteral(payload, true);
case SpringExpressionsLexer.FALSE:
return new BooleanLiteral(payload, false);
case SpringExpressionsLexer.OR:
return new OperatorOr(payload);
case SpringExpressionsLexer.AND:
return new OperatorAnd(payload);
case SpringExpressionsLexer.BANG:
return new OperatorNot(payload);
case SpringExpressionsLexer.REAL_LITERAL:
return new RealLiteral(payload);
case SpringExpressionsLexer.INTEGER_LITERAL:
return Literal.getIntLiteral(payload, 10);
case SpringExpressionsLexer.HEXADECIMAL_INTEGER_LITERAL:
return Literal.getIntLiteral(payload, 16);
case SpringExpressionsLexer.NOT_EQUAL:
return new OperatorInequality(payload);
case SpringExpressionsLexer.EQUAL:
return new OperatorEquality(payload);
case SpringExpressionsLexer.GREATER_THAN:
return new OperatorGreaterThan(payload);
case SpringExpressionsLexer.LESS_THAN:
return new OperatorLessThan(payload);
case SpringExpressionsLexer.LESS_THAN_OR_EQUAL:
return new OperatorLessThanOrEqual(payload);
case SpringExpressionsLexer.GREATER_THAN_OR_EQUAL:
return new OperatorGreaterThanOrEqual(payload);
case SpringExpressionsLexer.PLUS:
return new OperatorPlus(payload);
case SpringExpressionsLexer.MINUS:
return new OperatorMinus(payload);
case SpringExpressionsLexer.STAR/* MULTIPLY */:
return new OperatorMultiply(payload);
case SpringExpressionsLexer.DIV/* DIVIDE */:
return new OperatorDivide(payload);
case SpringExpressionsLexer.MOD:
return new OperatorModulus(payload);
case SpringExpressionsLexer.STRING_LITERAL:
case SpringExpressionsLexer.DQ_STRING_LITERAL:
return new StringLiteral(payload);
case SpringExpressionsLexer.NULL_LITERAL:
return new NullLiteral(payload);
case SpringExpressionsLexer.ID:
return new Identifier(payload);
case SpringExpressionsLexer.PROPERTY_OR_FIELD:
return new PropertyOrFieldReference(payload);
case SpringExpressionsLexer.METHOD:
return new MethodReference(payload);
case SpringExpressionsLexer.QUALIFIED_IDENTIFIER:
return new QualifiedIdentifier(payload);
case SpringExpressionsLexer.TYPEREF:
return new TypeReference(payload);
case SpringExpressionsLexer.EXPRESSION:
return new CompoundExpression(payload);
case SpringExpressionsLexer.CONSTRUCTOR:
return new ConstructorReference(payload, false);
case SpringExpressionsLexer.VARIABLEREF:
return new VariableReference(payload);
case SpringExpressionsLexer.FUNCTIONREF:
return new FunctionReference(payload);
case SpringExpressionsLexer.PROJECT:
return new Projection(payload);
case SpringExpressionsLexer.SELECT:
return new Selection(payload, Selection.ALL);
case SpringExpressionsLexer.SELECT_FIRST:
return new Selection(payload, Selection.FIRST);
case SpringExpressionsLexer.SELECT_LAST:
return new Selection(payload, Selection.LAST);
case SpringExpressionsLexer.ASSIGN:
return new Assign(payload);
case SpringExpressionsLexer.QMARK:
return new Ternary(payload);
case SpringExpressionsLexer.INDEXER:
return new Indexer(payload);
case SpringExpressionsLexer.BETWEEN:
return new OperatorBetween(payload);
case SpringExpressionsLexer.MATCHES:
return new OperatorMatches(payload);
case SpringExpressionsLexer.INSTANCEOF:
return new OperatorInstanceof(payload);
case SpringExpressionsLexer.RPAREN:
return new Placeholder(payload);
case SpringExpressionsLexer.COLON:
return new Placeholder(payload);
case SpringExpressionsLexer.DOT:
return new Dot(payload);
default:
throw new RuntimeException("Not implemented for '" + payload + "' " + getToken(payload) + "' "
+ payload.getType());
}
}
return new EmptySpelNode(payload);
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册