Browse Source

First drop of SPEL

conversation
Andy Clement 16 years ago
parent
commit
d8743000a0
  1. 44
      org.springframework.expression/src/main/java/org/springframework/expression/AccessException.java
  2. 57
      org.springframework.expression/src/main/java/org/springframework/expression/CacheablePropertyAccessor.java
  3. 43
      org.springframework.expression/src/main/java/org/springframework/expression/ConstructorExecutor.java
  4. 39
      org.springframework.expression/src/main/java/org/springframework/expression/ConstructorResolver.java
  5. 87
      org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java
  6. 100
      org.springframework.expression/src/main/java/org/springframework/expression/EvaluationException.java
  7. 43
      org.springframework.expression/src/main/java/org/springframework/expression/MethodExecutor.java
  8. 38
      org.springframework.expression/src/main/java/org/springframework/expression/MethodResolver.java
  9. 26
      org.springframework.expression/src/main/java/org/springframework/expression/Operation.java
  10. 38
      org.springframework.expression/src/main/java/org/springframework/expression/OperatorOverloader.java
  11. 90
      org.springframework.expression/src/main/java/org/springframework/expression/ParseException.java
  12. 89
      org.springframework.expression/src/main/java/org/springframework/expression/PropertyAccessor.java
  13. 40
      org.springframework.expression/src/main/java/org/springframework/expression/PropertyReaderExecutor.java
  14. 40
      org.springframework.expression/src/main/java/org/springframework/expression/PropertyWriterExecutor.java
  15. 46
      org.springframework.expression/src/main/java/org/springframework/expression/TypeComparator.java
  16. 52
      org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java
  17. 38
      org.springframework.expression/src/main/java/org/springframework/expression/TypeLocator.java
  18. 54
      org.springframework.expression/src/main/java/org/springframework/expression/TypeUtils.java

44
org.springframework.expression/src/main/java/org/springframework/expression/AccessException.java

@ -0,0 +1,44 @@ @@ -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);
}
}

57
org.springframework.expression/src/main/java/org/springframework/expression/CacheablePropertyAccessor.java

@ -0,0 +1,57 @@ @@ -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);
}
}

43
org.springframework.expression/src/main/java/org/springframework/expression/ConstructorExecutor.java

@ -0,0 +1,43 @@ @@ -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;
}

39
org.springframework.expression/src/main/java/org/springframework/expression/ConstructorResolver.java

@ -0,0 +1,39 @@ @@ -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;
}

87
org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java

@ -0,0 +1,87 @@ @@ -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();
}

100
org.springframework.expression/src/main/java/org/springframework/expression/EvaluationException.java

@ -0,0 +1,100 @@ @@ -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;
}
}

43
org.springframework.expression/src/main/java/org/springframework/expression/MethodExecutor.java

@ -0,0 +1,43 @@ @@ -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;
}

38
org.springframework.expression/src/main/java/org/springframework/expression/MethodResolver.java

@ -0,0 +1,38 @@ @@ -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;
}

26
org.springframework.expression/src/main/java/org/springframework/expression/Operation.java

@ -0,0 +1,26 @@ @@ -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;
}

38
org.springframework.expression/src/main/java/org/springframework/expression/OperatorOverloader.java

@ -0,0 +1,38 @@ @@ -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;
}

90
org.springframework.expression/src/main/java/org/springframework/expression/ParseException.java

@ -0,0 +1,90 @@ @@ -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;
}
}

89
org.springframework.expression/src/main/java/org/springframework/expression/PropertyAccessor.java

@ -0,0 +1,89 @@ @@ -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;
}

40
org.springframework.expression/src/main/java/org/springframework/expression/PropertyReaderExecutor.java

@ -0,0 +1,40 @@ @@ -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;
}

40
org.springframework.expression/src/main/java/org/springframework/expression/PropertyWriterExecutor.java

@ -0,0 +1,40 @@ @@ -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;
}

46
org.springframework.expression/src/main/java/org/springframework/expression/TypeComparator.java

@ -0,0 +1,46 @@ @@ -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);
}

52
org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java

@ -0,0 +1,52 @@ @@ -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);
}

38
org.springframework.expression/src/main/java/org/springframework/expression/TypeLocator.java

@ -0,0 +1,38 @@ @@ -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;
}

54
org.springframework.expression/src/main/java/org/springframework/expression/TypeUtils.java

@ -0,0 +1,54 @@ @@ -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…
Cancel
Save