Andy Clement
16 years ago
18 changed files with 964 additions and 0 deletions
@ -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); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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(); |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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); |
||||
|
||||
} |
@ -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); |
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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…
Reference in new issue