first commit
commit
5ce9a8a5d4
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>SpelHelper</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.maven.ide.eclipse.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.maven.ide.eclipse.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="Maven: org.springframework:spring-core:3.0.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" exported="" name="Maven: org.springframework:spring-asm:3.0.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" exported="" name="Maven: commons-logging:commons-logging:1.1.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="Maven: org.springframework:spring-expression:3.0.2.RELEASE" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
@ -0,0 +1,47 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.abhinavsarkar.spelhelper</groupId>
|
||||
<artifactId>SpelHelper</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>SpelHelper</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,38 @@
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
final class ExtensionFunctions {
|
||||
|
||||
public static <T> List<T> list(final T... args) {
|
||||
return unmodifiableList(Arrays.asList(args));
|
||||
}
|
||||
|
||||
public static <T> Set<T> set(final T... args) {
|
||||
return unmodifiableSet(new HashSet<T>(list(args)));
|
||||
}
|
||||
|
||||
public static <K,V> Map<K,V> map(final List<? extends K> keys,
|
||||
final List<? extends V> values) {
|
||||
Assert.isTrue(keys.size() == values.size(),
|
||||
"There should equal number of keys and values");
|
||||
Map<K,V> map = new HashMap<K,V>();
|
||||
int length = keys.size();
|
||||
for (int i = 0; i < length; i++) {
|
||||
map.put(keys.get(i), values.get(i));
|
||||
}
|
||||
return unmodifiableMap(map);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.ConstructorExecutor;
|
||||
import org.springframework.expression.ConstructorResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
|
||||
|
||||
final class ImplicitConstructorResolver implements
|
||||
ConstructorResolver {
|
||||
|
||||
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
|
||||
|
||||
public ConstructorExecutor resolve(final EvaluationContext context,
|
||||
final String typeName, final Class<?>[] argumentTypes) throws AccessException {
|
||||
try {
|
||||
return delegate.resolve(context, typeName, argumentTypes);
|
||||
} catch (AccessException ex) {
|
||||
Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
|
||||
.lookupImplicitConstructor(typeName + Arrays.toString(argumentTypes));
|
||||
if (variable instanceof Constructor<?>) {
|
||||
Constructor<?> constructor = (Constructor<?>) variable;
|
||||
return delegate.resolve(context, constructor.getDeclaringClass().getName(), argumentTypes);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.MethodExecutor;
|
||||
import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.support.ReflectiveMethodResolver;
|
||||
|
||||
public final class ImplicitMethodResolver implements MethodResolver {
|
||||
|
||||
private static final ConcurrentHashMap<String, MethodExecutor> cache =
|
||||
new ConcurrentHashMap<String, MethodExecutor>();
|
||||
|
||||
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||
final Object... arguments) throws AccessException {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private static final class ImplicitMethodExecutor implements
|
||||
MethodExecutor {
|
||||
private final MethodExecutor executor;
|
||||
|
||||
private ImplicitMethodExecutor(final MethodExecutor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||
final Object... arguments) throws AccessException {
|
||||
Object[] modifiedArguments = new Object[arguments.length + 1];
|
||||
modifiedArguments[0] = target;
|
||||
System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length);
|
||||
return executor.execute(context, null, modifiedArguments);
|
||||
}
|
||||
}
|
||||
|
||||
public MethodExecutor resolve(final EvaluationContext context,
|
||||
final Object targetObject, final String name, final Class<?>[] argumentTypes)
|
||||
throws AccessException {
|
||||
if (targetObject == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> type = targetObject.getClass();
|
||||
String cacheKey = type.getName() + "." + name;
|
||||
if (cache.containsKey(cacheKey)) {
|
||||
MethodExecutor executor = cache.get(cacheKey);
|
||||
return executor == NULL_ME ? null : executor;
|
||||
}
|
||||
|
||||
Method method = lookupMethod(context, type, name);
|
||||
if (method != null) {
|
||||
int modifiers = method.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Class<?> firstParameterType = parameterTypes[0];
|
||||
if (parameterTypes.length > 0
|
||||
&& firstParameterType.isAssignableFrom(type)) {
|
||||
|
||||
Class<?>[] modifiedArgumentTypes = new Class[argumentTypes.length + 1];
|
||||
modifiedArgumentTypes[0] = firstParameterType;
|
||||
System.arraycopy(argumentTypes, 0, modifiedArgumentTypes,
|
||||
1, argumentTypes.length);
|
||||
MethodExecutor executor = new ReflectiveMethodResolver()
|
||||
.resolve(context, method.getDeclaringClass(), name,
|
||||
modifiedArgumentTypes);
|
||||
MethodExecutor wrappedExecutor = executor == null ? null
|
||||
: new ImplicitMethodExecutor(executor);
|
||||
cache.putIfAbsent(cacheKey, wrappedExecutor);
|
||||
return wrappedExecutor;
|
||||
}
|
||||
}
|
||||
}
|
||||
cache.putIfAbsent(cacheKey, NULL_ME);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method lookupMethod(final EvaluationContext context,
|
||||
final Class<?> type, final String name) {
|
||||
for (Class<?> clazz : InheritenceUtil.getInheritance(type)) {
|
||||
Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
|
||||
.lookupImplicitMethod(clazz.getName() + "." + name);
|
||||
if (variable instanceof Method) {
|
||||
return (Method) variable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
final class ImplicitMethods {
|
||||
|
||||
public static <T> Set<T> distinct(final List<? extends T> list) {
|
||||
return unmodifiableSet(new HashSet<T>(list));
|
||||
}
|
||||
|
||||
public static <T extends Comparable<? super T>> List<T> sorted(
|
||||
final List<? extends T> list) {
|
||||
List<T> temp = new ArrayList<T>(list);
|
||||
Collections.sort(temp);
|
||||
return unmodifiableList(temp);
|
||||
}
|
||||
|
||||
public static <T> List<T> reversed(final List<? extends T> list) {
|
||||
List<T> temp = new ArrayList<T>(list);
|
||||
Collections.reverse(temp);
|
||||
return unmodifiableList(temp);
|
||||
}
|
||||
|
||||
public static <T> List<T> take(final List<T> list, final int n) {
|
||||
return unmodifiableList(list.subList(0, n));
|
||||
}
|
||||
|
||||
public static <T> List<T> drop(final List<T> list, final int n) {
|
||||
return unmodifiableList(list.subList(n, list.size()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.MethodExecutor;
|
||||
import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
||||
|
||||
private static final ConcurrentHashMap<String, MethodExecutor> cache =
|
||||
new ConcurrentHashMap<String, MethodExecutor>();
|
||||
|
||||
public boolean canRead(final EvaluationContext context,
|
||||
final Object target, final String name)
|
||||
throws AccessException {
|
||||
Assert.notNull(target, "target is null");
|
||||
String cacheKey = target.getClass().getName() + "." + name;
|
||||
if (cache.containsKey(cacheKey)) {
|
||||
return cache.get(cacheKey) != null;
|
||||
}
|
||||
|
||||
for (MethodResolver mr : context.getMethodResolvers()) {
|
||||
MethodExecutor me = mr.resolve(context, target, name, new Class[0]);
|
||||
if (me != null) {
|
||||
cache.putIfAbsent(cacheKey, me);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
cache.putIfAbsent(cacheKey, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
public TypedValue read(final EvaluationContext context,
|
||||
final Object target, final String name)
|
||||
throws AccessException {
|
||||
if (canRead(context, target, name)) {
|
||||
String cacheKey = target.getClass().getName() + "." + name;
|
||||
return cache.get(cacheKey).execute(context, target, new Object[0]);
|
||||
}
|
||||
throw new AccessException(MessageFormat.format(
|
||||
"Cannot read property: {0} of target: {1}", name, target));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
final class InheritenceUtil {
|
||||
|
||||
public static Set<Class<?>> getInheritance(final Class<?> in) {
|
||||
LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>();
|
||||
result.add(in);
|
||||
getInheritance(in, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get inheritance of type.
|
||||
*
|
||||
* @param in
|
||||
* @param result
|
||||
*/
|
||||
private static void getInheritance(final Class<?> in, final Set<Class<?>> result) {
|
||||
Class<?> superclass = getSuperclass(in);
|
||||
|
||||
if (superclass != null) {
|
||||
result.add(superclass);
|
||||
getInheritance(superclass, result);
|
||||
}
|
||||
|
||||
getInterfaceInheritance(in, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interfaces that the type inherits from.
|
||||
*
|
||||
* @param in
|
||||
* @param result
|
||||
*/
|
||||
private static void getInterfaceInheritance(final Class<?> in,
|
||||
final Set<Class<?>> result) {
|
||||
for (Class<?> c : in.getInterfaces()) {
|
||||
result.add(c);
|
||||
getInterfaceInheritance(c, result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get superclass of class.
|
||||
*
|
||||
* @param in
|
||||
* @return
|
||||
*/
|
||||
private static Class<?> getSuperclass(final Class<?> in) {
|
||||
if (in == null) {
|
||||
return null;
|
||||
}
|
||||
if (in.isArray() && in != Object[].class) {
|
||||
Class<?> type = in.getComponentType();
|
||||
while (type.isArray()) {
|
||||
type = type.getComponentType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
return in.getSuperclass();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
|
||||
public abstract class ReadOnlyGenericPropertyAccessor implements
|
||||
PropertyAccessor {
|
||||
|
||||
public final boolean canWrite(final EvaluationContext context,
|
||||
final Object target, final String name) throws AccessException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final Class[] getSpecificTargetClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void write(final EvaluationContext context, final Object target,
|
||||
final String name, final Object newValue) throws AccessException {
|
||||
throw new AccessException(MessageFormat.format(
|
||||
"Cannot write property: {0} of target: {1}", name, target));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.expression.ConstructorResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public final class SpelHelper {
|
||||
|
||||
public static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName();
|
||||
|
||||
private static final ExpressionParser PARSER = new SpelExpressionParser();
|
||||
private static final ThreadLocal<EvaluationContext> currentContext =
|
||||
new ThreadLocal<EvaluationContext>();
|
||||
|
||||
private volatile EvaluationContext context;
|
||||
private final Set<Method> registeredFunctions = new HashSet<Method>();
|
||||
private final Map<String,Method> registeredMethods =
|
||||
new ConcurrentHashMap<String, Method>();
|
||||
private final Map<String,Constructor<?>> registeredConstructors =
|
||||
new ConcurrentHashMap<String, Constructor<?>>();
|
||||
|
||||
{
|
||||
registerFunctionsFromClass(ExtensionFunctions.class);
|
||||
registerImplicitMethodsFromClass(ImplicitMethods.class);
|
||||
}
|
||||
|
||||
public SpelHelper registerImplicitMethodsFromClass(final Class<?> clazz) {
|
||||
for (Method method : filterMethods(clazz)) {
|
||||
registeredMethods.put(String.format(
|
||||
"%s.%s", method.getParameterTypes()[0].getName(), method.getName()),
|
||||
method);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpelHelper registerFunctionsFromClass(final Class<?> clazz) {
|
||||
registeredFunctions.addAll(filterMethods(clazz));
|
||||
context = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpelHelper registerImplicitConstructorsFromClass(final Class<?> clazz) {
|
||||
for (Constructor<?> constructor : asList(clazz.getConstructors())) {
|
||||
registeredConstructors.put(
|
||||
constructor.getDeclaringClass().getSimpleName()
|
||||
+ Arrays.toString(constructor.getParameterTypes()),
|
||||
constructor);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> T evalExpression(final String expressionString,
|
||||
final Object rootElement, final Class<T> desiredType) {
|
||||
EvaluationContext evaluationContext = getEvaluationContext(rootElement);
|
||||
currentContext.set(evaluationContext);
|
||||
T value = evalExpression(expressionString, evaluationContext, desiredType);
|
||||
currentContext.set(null);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public <T> T evalExpression(final String expressionString,
|
||||
final EvaluationContext evaluationContext, final Class<T> desiredType) {
|
||||
return PARSER.parseExpression(expressionString)
|
||||
.getValue(evaluationContext, desiredType);
|
||||
}
|
||||
|
||||
public <T> T evalExpressions(final String[] expressionStrings,
|
||||
final Object rootElement, final Class<T> desiredType) {
|
||||
int length = expressionStrings.length;
|
||||
Assert.isTrue(length > 0,
|
||||
"expressionStrings should have length more than 0");
|
||||
for (int i = 0; i < length - 1; i++) {
|
||||
evalExpression(expressionStrings[i], rootElement, Object.class);
|
||||
}
|
||||
return evalExpression(expressionStrings[length - 1],
|
||||
rootElement, desiredType);
|
||||
}
|
||||
|
||||
private EvaluationContext getEvaluationContext(final Object rootObject) {
|
||||
if (context == null) {
|
||||
synchronized (PARSER) {
|
||||
if (context == null) {
|
||||
StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject);
|
||||
newContext.getMethodResolvers().add(new ImplicitMethodResolver());
|
||||
newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor());
|
||||
newContext.setConstructorResolvers(
|
||||
asList((ConstructorResolver) new ImplicitConstructorResolver()));
|
||||
for (Method method : registeredFunctions) {
|
||||
newContext.setVariable(method.getName(), method);
|
||||
}
|
||||
newContext.setVariable(CONTEXT_LOOKUP_KEY, this);
|
||||
context = newContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
public Method lookupImplicitMethod(final String lookup) {
|
||||
Assert.notNull(lookup);
|
||||
return registeredMethods.get(lookup);
|
||||
}
|
||||
|
||||
public Constructor<?> lookupImplicitConstructor(final String lookup) {
|
||||
Assert.notNull(lookup);
|
||||
return registeredConstructors.get(lookup);
|
||||
}
|
||||
|
||||
public static EvaluationContext getCurrentContext() {
|
||||
return currentContext.get();
|
||||
}
|
||||
|
||||
private static List<Method> filterMethods(final Class<?> clazz) {
|
||||
List<Method> allowedMethods = new ArrayList<Method>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
int modifiers = method.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
||||
&& !method.getReturnType().equals(Void.TYPE)
|
||||
&& method.getParameterTypes().length > 0) {
|
||||
allowedMethods.add(method);
|
||||
}
|
||||
}
|
||||
return allowedMethods;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package net.abhinavsarkar.spelhelper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SpelHelperTest {
|
||||
|
||||
@Test
|
||||
public void testRegisteredFunction() {
|
||||
Assert.assertEquals(
|
||||
Arrays.asList("abhinav", "mini", "dan"),
|
||||
new SpelHelper().evalExpression(
|
||||
"#list('abhinav','mini','dan')", new Object(), List.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitMethod() {
|
||||
Assert.assertEquals(
|
||||
Arrays.asList("abhinav", "dan", "mini"),
|
||||
new SpelHelper().evalExpression(
|
||||
"#list('abhinav','mini','dan').sorted", new Object(), List.class));
|
||||
}
|
||||
|
||||
public static final class ConstructorTest {
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
return o instanceof ConstructorTest;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitConstructor() {
|
||||
Assert.assertEquals(
|
||||
new ConstructorTest(),
|
||||
new SpelHelper()
|
||||
.registerImplicitConstructorsFromClass(ConstructorTest.class)
|
||||
.evalExpression("new ConstructorTest()", new Object(), ConstructorTest.class));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue