First drop of SPEL
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@6 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
f22f13f020
commit
c6d7197e10
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* An AccessException is thrown by an accessor if it has an unexpected problem.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class AccessException extends Exception {
|
||||
|
||||
/**
|
||||
* Create an AccessException with a specific message and cause.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public AccessException(String message, Exception cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an AccessException with a specific message.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public AccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package org.springframework.expression;
|
||||
|
||||
// TODO (asc) Do we need a 'caching is allowed' option to be configurable at parse time?
|
||||
/**
|
||||
* A CacheablePropertyAccessor is an optimized PropertyAccessor where the two parts of accessing the
|
||||
* property are separated: (1) resolving the property and (2) retrieving its value. In some cases there is
|
||||
* a large cost to discovering which property an expression refers to and once discovered it will
|
||||
* always resolve to the same property. In these situations a CacheablePropertyAccessor enables the
|
||||
* resolution to be done once and a reusable object (an executor) returned that can be called over and
|
||||
* over to retrieve the property value without going through resolution again.
|
||||
* <p>
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public abstract class CacheablePropertyAccessor implements PropertyAccessor {
|
||||
|
||||
/**
|
||||
* Attempt to resolve the named property and return an executor that can be called to
|
||||
* get the value of that property. Return null if the property cannot be resolved.
|
||||
*
|
||||
* @param context the evaluation context
|
||||
* @param target the target upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return a reusable executor that can retrieve the property value
|
||||
*/
|
||||
public abstract PropertyReaderExecutor getReaderAccessor(EvaluationContext context, Object target, Object name);
|
||||
|
||||
/**
|
||||
* Attempt to resolve the named property and return an executor that can be called to
|
||||
* set the value of that property. Return null if the property cannot be resolved.
|
||||
*
|
||||
* @param context the evaluation context
|
||||
* @param target the target upon which the property is being accessed
|
||||
* @param name the name of the property to be set
|
||||
* @return a reusable executor that can set the property value
|
||||
*/
|
||||
public abstract PropertyWriterExecutor getWriterAccessor(EvaluationContext context, Object target, Object name);
|
||||
|
||||
// Implementation of PropertyAccessor follows, based on the resolver/executor model
|
||||
|
||||
public final boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
return getReaderAccessor(context,target,name) != null;
|
||||
}
|
||||
|
||||
public final boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
return getWriterAccessor(context,target,name) != null;
|
||||
}
|
||||
|
||||
public final Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
return getReaderAccessor(context,target,name).execute(context,target);
|
||||
}
|
||||
|
||||
public final void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException {
|
||||
getWriterAccessor(context,target,name).execute(context,target,newValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
// TODO (asc) Is the resolver/executor model too pervasive in this package?
|
||||
/**
|
||||
* Executors are built by resolvers and can be cached by the infrastructure to repeat an operation quickly without going
|
||||
* back to the resolvers. For example, the particular constructor to run on a class may be discovered by the reflection
|
||||
* constructor resolver - it will then build a ConstructorExecutor that executes that constructor and the
|
||||
* ConstructorExecutor can be reused without needing to go back to the resolver to discover the constructor again.
|
||||
*
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the infrastructure to go
|
||||
* back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface ConstructorExecutor {
|
||||
|
||||
/**
|
||||
* Execute a constructor in the specified context using the specified arguments.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param arguments the arguments to the constructor call, should match (in terms of number and type) whatever the
|
||||
* command will need to run
|
||||
* @return the new object
|
||||
* @throws AccessException if there is a problem executing the command or the CommandExecutor is no longer valid
|
||||
*/
|
||||
Object execute(EvaluationContext context, Object... arguments) throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A constructor resolver attempts locate a constructor and returns a ConstructorExecutor that can be used to invoke
|
||||
* that constructor. The ConstructorExecutor will be cached but if it 'goes stale' the resolvers will be called again.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface ConstructorResolver {
|
||||
|
||||
/**
|
||||
* Within the supplied context determine a suitable constructor on the supplied type that can handle the specified
|
||||
* arguments. Return a ConstructorExecutor that can be used to invoke that constructor (or null if no constructor
|
||||
* could be found).
|
||||
*
|
||||
* @param context the current evaluation context
|
||||
* @param typename the type upon which to look for the constructor
|
||||
* @param argumentTypes the arguments that the constructor must be able to handle
|
||||
* @return a ConstructorExecutor that can invoke the constructor, or null if non found
|
||||
*/
|
||||
ConstructorExecutor resolve(EvaluationContext context, String typename, Class<?>[] argumentTypes)
|
||||
throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.standard.StandardTypeUtilities;
|
||||
|
||||
/**
|
||||
* Expressions are executed in an evaluation context. It is in this context that references are resolved when
|
||||
* encountered during expression evaluation.
|
||||
*
|
||||
* There is a default implementation of the EvaluationContext, {@link StandardEvaluationContext} that can be extended,
|
||||
* rather than having to implement everything.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface EvaluationContext {
|
||||
|
||||
/**
|
||||
* @return the root context object against which unqualified properties/methods/etc should be resolved
|
||||
*/
|
||||
Object getRootContextObject();
|
||||
|
||||
/**
|
||||
* @return a TypeUtilities implementation that can be used for looking up types, converting types, comparing types,
|
||||
* and overloading basic operators for types. A standard implementation is provided in {@link StandardTypeUtilities}
|
||||
*/
|
||||
TypeUtils getTypeUtils();
|
||||
|
||||
/**
|
||||
* Look up a named variable within this execution context.
|
||||
*
|
||||
* @param name variable to lookup
|
||||
* @return the value of the variable
|
||||
*/
|
||||
Object lookupVariable(String name);
|
||||
|
||||
/**
|
||||
* Set a named variable within this execution context to a specified value.
|
||||
*
|
||||
* @param name variable to set
|
||||
* @param value value to be placed in the variable
|
||||
*/
|
||||
void setVariable(String name, Object value);
|
||||
|
||||
// TODO (asc) lookupReference() - is it too expensive to return all objects within a context?
|
||||
/**
|
||||
* Look up an object reference in a particular context. If no contextName is specified (null), assume the default
|
||||
* context. If no objectName is specified (null), return all objects in the specified context (List<Object>).
|
||||
*
|
||||
* @param contextName the context in which to perform the lookup (or null for default context)
|
||||
* @param objectName the object to lookup in the context (or null to get all objects)
|
||||
* @return a specific object or List<Object>
|
||||
*/
|
||||
Object lookupReference(Object contextName, Object objectName) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* @return a list of resolvers that will be asked in turn to locate a constructor
|
||||
*/
|
||||
List<ConstructorResolver> getConstructorResolvers();
|
||||
|
||||
/**
|
||||
* @return a list of resolvers that will be asked in turn to locate a method
|
||||
*/
|
||||
List<MethodResolver> getMethodResolvers();
|
||||
|
||||
/**
|
||||
* @return a list of accessors that will be asked in turn to read/write a property
|
||||
*/
|
||||
List<PropertyAccessor> getPropertyAccessors();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
// TODO (asc) This class needs a better name? I might have used EvaluationException if it wasn't also used for parsing issues
|
||||
/**
|
||||
* Base class for exceptions occurring during expression parsing and evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class EvaluationException extends Exception {
|
||||
|
||||
/**
|
||||
* The expression string.
|
||||
*/
|
||||
private String expressionString;
|
||||
|
||||
/**
|
||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||
* setExpressionString().
|
||||
*
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public EvaluationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression parsing exception.
|
||||
*
|
||||
* @param expressionString the expression string that could not be parsed
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public EvaluationException(String expressionString, Throwable cause) {
|
||||
this(expressionString, "Exception occurred whilst handling '" + expressionString + "'", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public EvaluationException(String expressionString, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public EvaluationException(String expressionString, String message) {
|
||||
super(message);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||
* setExpressionString().
|
||||
*
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public EvaluationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expression string, called on exceptions where the expressionString is not known at the time of exception
|
||||
* creation.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
*/
|
||||
protected final void setExpressionString(String expressionString) {
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression string
|
||||
*/
|
||||
public final String getExpressionString() {
|
||||
return expressionString;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* MethodExecutors are built by the resolvers and can be cached by the infrastructure to repeat an operation quickly
|
||||
* without going back to the resolvers. For example, the particular method to run on an object may be discovered by the
|
||||
* reflection method resolver - it will then build a MethodExecutor that executes that method and the MethodExecutor can
|
||||
* be reused without needing to go back to the resolver to discover the method again.
|
||||
* <p>
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the infrastructure to go
|
||||
* back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface MethodExecutor {
|
||||
|
||||
/**
|
||||
* Execute a command using the specified arguments, and using the specified expression state.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param target the target object of the call - null for static methods
|
||||
* @param methodArguments the arguments to the executor, should match (in terms of number and type) whatever the
|
||||
* command will need to run
|
||||
* @return the value returned from execution
|
||||
* @throws AccessException if there is a problem executing the command or the MethodExecutor is no longer valid
|
||||
*/
|
||||
Object execute(EvaluationContext context, Object target, Object... methodArguments) throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A method resolver attempts locate a method and returns a command executor that can be used to invoke that method. The
|
||||
* command executor will be cached but if it 'goes stale' the resolvers will be called again.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface MethodResolver {
|
||||
|
||||
/**
|
||||
* Within the supplied context determine a suitable method on the supplied object that can handle the specified
|
||||
* arguments. Return a MethodExecutor that can be used to invoke that method (or null if no method
|
||||
* could be found).
|
||||
*
|
||||
* @param context the current evaluation context
|
||||
* @param targetObject the object upon which the method is being called
|
||||
* @param argumentTypes the arguments that the constructor must be able to handle
|
||||
* @return a MethodExecutor that can invoke the method, or null if the method cannot be found
|
||||
*/
|
||||
MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, Class<?>[] argumentTypes) throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* Supported operations that an {@link OperatorOverloader} can implement for any pair of operands.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public enum Operation {
|
||||
ADD, SUBTRACT, DIVIDE, MULTIPLY, MODULUS;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package org.springframework.expression;
|
||||
|
||||
|
||||
/**
|
||||
* By default the mathematical operators {@link Operation} support simple types like numbers. By providing an
|
||||
* implementation of OperatorOverloader, a user of the expression language can support these operations on other types.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface OperatorOverloader {
|
||||
|
||||
// TODO (asc) does this need a better type name?
|
||||
// TODO (asc) needs some testing!
|
||||
|
||||
/**
|
||||
* Return true if the operator overloader supports the specified operation between the two operands and so should be
|
||||
* invoked to handle it.
|
||||
*
|
||||
* @param operation the operation to be performed
|
||||
* @param leftOperand the left operand
|
||||
* @param rightOperand the right operand
|
||||
* @return true if the OperatorOverloader supports the specified operation between the two operands
|
||||
* @throws EvaluationException if there is a problem performing the operation
|
||||
*/
|
||||
boolean overridesOperation(Operation operation, Object leftOperand, Object rightOperand) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Execute the specified operation on two operands, returning a result. See {@link Operation} for supported
|
||||
* operations.
|
||||
*
|
||||
* @param operation the operation to be performed
|
||||
* @param leftOperand the left operand
|
||||
* @param rightOperand the right operand
|
||||
* @return the result of performing the operation on the two operands
|
||||
* @throws EvaluationException if there is a problem performing the operation
|
||||
*/
|
||||
Object operate(Operation operation, Object leftOperand, Object rightOperand) throws EvaluationException;
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
// TODO (asc) This class needs a better name? I might have used EvaluationException if it wasn't also used for parsing issues
|
||||
/**
|
||||
* Base class for exceptions occurring during expression parsing and evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ParseException extends Exception {
|
||||
|
||||
/**
|
||||
* The expression string.
|
||||
*/
|
||||
private String expressionString;
|
||||
|
||||
/**
|
||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||
* setExpressionString().
|
||||
*
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression parsing exception.
|
||||
*
|
||||
* @param expressionString the expression string that could not be parsed
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ParseException(String expressionString, Throwable cause) {
|
||||
this(expressionString, "Exception occurred whilst handling '" + expressionString + "'", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ParseException(String expressionString, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public ParseException(String expressionString, String message) {
|
||||
super(message);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expression string, called on exceptions where the expressionString is not known at the time of exception
|
||||
* creation.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
*/
|
||||
protected final void setExpressionString(String expressionString) {
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression string
|
||||
*/
|
||||
public final String getExpressionString() {
|
||||
return expressionString;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A property accessor is able to read (and possibly write) to object properties. The interface places no restrictions
|
||||
* and so implementors are free to access properties directly as fields or through getters or in any other way they see
|
||||
* as appropriate. A resolver can optionally specify an array of target classes for which it should be called - but if
|
||||
* it returns null from getSpecificTargetClasses() then it will be called for all property references and given a chance
|
||||
* to determine if it can read or write them. Property resolvers are considered to be ordered and each will be called in
|
||||
* turn. The only rule that affects the call order is that any naming the target class directly in
|
||||
* getSpecifiedTargetClasses() will be called first, before the general resolvers.
|
||||
* <p>
|
||||
* If the cost of locating the property is expensive, in relation to actually retrieving its value, consider
|
||||
* extending CacheablePropertyAccessor rather than directly implementing PropertyAccessor. A CacheablePropertyAccessor
|
||||
* enables the discovery (resolution) of the property to be done once and then an object (an executor) returned
|
||||
* and cached by the infrastructure that can be used repeatedly to retrieve the property value.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface PropertyAccessor {
|
||||
|
||||
/**
|
||||
* Return an array of classes for which this resolver should be called. Returning null indicates this is a general
|
||||
* resolver that can be called in an attempt to resolve a property on any type.
|
||||
*
|
||||
* @return an array of classes that this resolver is suitable for (or null if a general resolver)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class[] getSpecificTargetClasses();
|
||||
|
||||
/**
|
||||
* Called to determine if a resolver instance is able to access a specified property on a specified target object.
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return true if this resolver is able to read the property
|
||||
* @throws AccessException if there is any problem determining whether the property can be read
|
||||
*/
|
||||
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException;
|
||||
|
||||
/**
|
||||
* Called to read a property from a specified target object
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return Object the value of the property
|
||||
* @throws AccessException if there is any problem accessing the property value
|
||||
*/
|
||||
public Object read(EvaluationContext context, Object target, Object name) throws AccessException;
|
||||
|
||||
/**
|
||||
* Called to determine if a resolver instance is able to write to a specified property on a specified target object.
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return true if this resolver is able to write to the property
|
||||
* @throws AccessException if there is any problem determining whether the property can be written to
|
||||
*/
|
||||
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException;
|
||||
|
||||
/**
|
||||
* Called to write to a property on a specified target object. Should only succeed if canWrite() also returns true.
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @param newValue the new value for the property
|
||||
* @throws AccessException if there is any problem writing to the property value
|
||||
*/
|
||||
public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* If a property accessor is built upon the CacheablePropertyAccessor class then once the property
|
||||
* has been resolved the accessor will return an instance of this PropertyReaderExecutor interface
|
||||
* that can be cached and repeatedly called to access the value of the property.
|
||||
* <p>
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the
|
||||
* infrastructure to go back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface PropertyReaderExecutor {
|
||||
|
||||
/**
|
||||
* Return the value of a property for the specified target.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param targetObject the target object on which property access is being attempted
|
||||
* @return the property value
|
||||
* @throws AccessException if there is a problem accessing the property or this executor has become stale
|
||||
*/
|
||||
Object execute(EvaluationContext context, Object targetObject) throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* If a property accessor is built upon the CacheablePropertyAccessor class then once the property
|
||||
* has been resolved the accessor will return an instance of this PropertyWriterExecutor interface
|
||||
* that can be cached and repeatedly called to set the value of the property.
|
||||
* <p>
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the
|
||||
* infrastructure to go back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface PropertyWriterExecutor {
|
||||
|
||||
/**
|
||||
* Set the value of a property to the supplied new value.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param targetObject the target object on which property write is being attempted
|
||||
* @param newValue the new value for the property
|
||||
* @throws AccessException if there is a problem setting the property or this executor has become stale
|
||||
*/
|
||||
void execute(EvaluationContext evaluationContext, Object targetObject, Object newValue) throws AccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Instances of a type comparator should be able to compare pairs of objects for equality, the specification of the
|
||||
* return value is the same as for {@link Comparable}.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeComparator {
|
||||
|
||||
/**
|
||||
* Compare two objects.
|
||||
*
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return 0 if they are equal, <0 if the first is smaller than the second, or >0 if the first is larger than the
|
||||
* second
|
||||
* @throws EvaluationException if a problem occurs during comparison (or they are not comparable)
|
||||
*/
|
||||
int compare(Object firstObject, Object secondObject) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Return true if the comparator can compare these two objects
|
||||
*
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return true if the comparator can compare these objects
|
||||
*/
|
||||
public boolean canCompare(Object firstObject, Object secondObject);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.expression.spel.standard.StandardIndividualTypeConverter;
|
||||
import org.springframework.expression.spel.standard.StandardTypeConverter;
|
||||
|
||||
/**
|
||||
* A type converter can convert values between different types. There is a default implementation called {@link StandardTypeConverter}
|
||||
* that supports some basic conversions. That default implementation can be extended through subclassing or
|
||||
* via registration of new {@link StandardIndividualTypeConverter} instances with the StandardTypeConverter.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeConverter {
|
||||
// TODO (asc) replace this stuff with Keiths spring-binding conversion code
|
||||
// TODO (asc) should ExpressionException be thrown for lost precision in the case of coercion?
|
||||
|
||||
/**
|
||||
* Convert (may coerce) a value from one type to another, for example from a boolean to a string.
|
||||
*
|
||||
* @param value the value to be converted
|
||||
* @param targetType the type that the value should be converted to if possible
|
||||
* @return the converted value
|
||||
* @throws EvaluationException if conversion is not possible
|
||||
*/
|
||||
Object convertValue(Object value, Class<?> targetType) throws EvaluationException;
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the type converter can convert the specified type to the desired target type.
|
||||
*
|
||||
* @param sourceType the type to be converted from
|
||||
* @param targetType the type to be converted to
|
||||
* @return true if that conversion can be performed
|
||||
*/
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.expression.spel.standard.StandardTypeLocator;
|
||||
|
||||
/**
|
||||
* Implementors of this interface are expected to be able to locate types. They may use custom classloaders or the
|
||||
* and deal with common package prefixes (java.lang, etc) however they wish. See
|
||||
* {@link StandardTypeLocator} for an example implementation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeLocator {
|
||||
|
||||
/**
|
||||
* Find a type by name. The name may or may not be fully qualified (eg. String or java.lang.String)
|
||||
*
|
||||
* @param type the type to be located
|
||||
* @return the class object representing that type
|
||||
* @throw ExpressionException if there is a problem finding it
|
||||
*/
|
||||
Class<?> findType(String typename) throws EvaluationException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* TypeUtilities brings together the various kinds of type related function that may occur
|
||||
* whilst working with expressions. An implementor is providing support for four type related
|
||||
* facilities:
|
||||
* <ul>
|
||||
* <li>a mechanism for finding types
|
||||
* <li>a mechanism for comparing types
|
||||
* <li>a mechanism for type conversion/coercion
|
||||
* <li>a mechanism for overloading mathematical operations (add/subtract/etc)
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeUtils {
|
||||
|
||||
/**
|
||||
* @return a type locator that can be used to find types, either by short or fully qualified name.
|
||||
*/
|
||||
TypeLocator getTypeLocator();
|
||||
|
||||
/**
|
||||
* @return a type comparator for comparing pairs of objects for equality.
|
||||
*/
|
||||
TypeComparator getTypeComparator();
|
||||
|
||||
/**
|
||||
* @return a type converter that can convert (or coerce) a value from one type to another.
|
||||
*/
|
||||
TypeConverter getTypeConverter();
|
||||
|
||||
/**
|
||||
* @return an operator overloader that may support mathematical operations between more than the standard set of
|
||||
* types
|
||||
*/
|
||||
OperatorOverloader getOperatorOverloader();
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue