Browse Source

first commit

Abhinav Sarkar 10 years ago
commit
5ce9a8a5d4

+ 8
- 0
.classpath View File

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<classpath>
3
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
4
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
5
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
6
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
7
+	<classpathentry kind="output" path="target/classes"/>
8
+</classpath>

+ 23
- 0
.project View File

@@ -0,0 +1,23 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<projectDescription>
3
+	<name>SpelHelper</name>
4
+	<comment></comment>
5
+	<projects>
6
+	</projects>
7
+	<buildSpec>
8
+		<buildCommand>
9
+			<name>org.eclipse.jdt.core.javabuilder</name>
10
+			<arguments>
11
+			</arguments>
12
+		</buildCommand>
13
+		<buildCommand>
14
+			<name>org.maven.ide.eclipse.maven2Builder</name>
15
+			<arguments>
16
+			</arguments>
17
+		</buildCommand>
18
+	</buildSpec>
19
+	<natures>
20
+		<nature>org.eclipse.jdt.core.javanature</nature>
21
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
22
+	</natures>
23
+</projectDescription>

+ 20
- 0
SpelHelper.iml View File

@@ -0,0 +1,20 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
3
+  <component name="NewModuleRootManager" inherit-compiler-output="false">
4
+    <output url="file://$MODULE_DIR$/target/classes" />
5
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
6
+    <content url="file://$MODULE_DIR$">
7
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
8
+      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
9
+      <excludeFolder url="file://$MODULE_DIR$/target" />
10
+    </content>
11
+    <orderEntry type="inheritedJdk" />
12
+    <orderEntry type="sourceFolder" forTests="false" />
13
+    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.1" level="project" />
14
+    <orderEntry type="library" exported="" name="Maven: org.springframework:spring-core:3.0.2.RELEASE" level="project" />
15
+    <orderEntry type="library" exported="" name="Maven: org.springframework:spring-asm:3.0.2.RELEASE" level="project" />
16
+    <orderEntry type="library" exported="" name="Maven: commons-logging:commons-logging:1.1.1" level="project" />
17
+    <orderEntry type="library" exported="" name="Maven: org.springframework:spring-expression:3.0.2.RELEASE" level="project" />
18
+  </component>
19
+</module>
20
+

+ 47
- 0
pom.xml View File

@@ -0,0 +1,47 @@
1
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3
+  <modelVersion>4.0.0</modelVersion>
4
+
5
+  <groupId>net.abhinavsarkar.spelhelper</groupId>
6
+  <artifactId>SpelHelper</artifactId>
7
+  <version>1.0</version>
8
+  <packaging>jar</packaging>
9
+
10
+  <name>SpelHelper</name>
11
+  <url>http://maven.apache.org</url>
12
+
13
+  <properties>
14
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15
+  </properties>
16
+  
17
+  <build>
18
+  	<plugins>
19
+  	  <plugin>
20
+        <artifactId>maven-compiler-plugin</artifactId>
21
+        <configuration>
22
+          <source>1.5</source>
23
+          <target>1.5</target>
24
+        </configuration>
25
+      </plugin>
26
+  	</plugins>
27
+  </build>
28
+
29
+  <dependencies>
30
+    <dependency>
31
+      <groupId>junit</groupId>
32
+      <artifactId>junit</artifactId>
33
+      <version>4.4</version>
34
+      <scope>test</scope>
35
+    </dependency>
36
+    <dependency>
37
+      <groupId>org.springframework</groupId>
38
+      <artifactId>spring-core</artifactId>
39
+      <version>3.0.2.RELEASE</version>
40
+    </dependency>
41
+    <dependency>
42
+      <groupId>org.springframework</groupId>
43
+      <artifactId>spring-expression</artifactId>
44
+      <version>3.0.2.RELEASE</version>
45
+    </dependency>
46
+  </dependencies>
47
+</project>

+ 38
- 0
src/main/java/net/abhinavsarkar/spelhelper/ExtensionFunctions.java View File

@@ -0,0 +1,38 @@
1
+package net.abhinavsarkar.spelhelper;
2
+
3
+import static java.util.Collections.unmodifiableList;
4
+import static java.util.Collections.unmodifiableMap;
5
+import static java.util.Collections.unmodifiableSet;
6
+
7
+import java.util.Arrays;
8
+import java.util.HashMap;
9
+import java.util.HashSet;
10
+import java.util.List;
11
+import java.util.Map;
12
+import java.util.Set;
13
+
14
+import org.springframework.util.Assert;
15
+
16
+final class ExtensionFunctions {
17
+
18
+    public static <T> List<T> list(final T... args) {
19
+        return unmodifiableList(Arrays.asList(args));
20
+    }
21
+
22
+    public static <T> Set<T> set(final T... args) {
23
+        return unmodifiableSet(new HashSet<T>(list(args)));
24
+    }
25
+
26
+    public static <K,V> Map<K,V> map(final List<? extends K> keys,
27
+    		final List<? extends V> values) {
28
+        Assert.isTrue(keys.size() == values.size(),
29
+                "There should equal number of keys and values");
30
+        Map<K,V> map = new HashMap<K,V>();
31
+        int length = keys.size();
32
+        for (int i = 0; i < length; i++) {
33
+            map.put(keys.get(i), values.get(i));
34
+        }
35
+        return unmodifiableMap(map);
36
+    }
37
+
38
+}

+ 34
- 0
src/main/java/net/abhinavsarkar/spelhelper/ImplicitConstructorResolver.java View File

@@ -0,0 +1,34 @@
1
+/**
2
+ *
3
+ */
4
+package net.abhinavsarkar.spelhelper;
5
+
6
+import java.lang.reflect.Constructor;
7
+import java.util.Arrays;
8
+
9
+import org.springframework.expression.AccessException;
10
+import org.springframework.expression.ConstructorExecutor;
11
+import org.springframework.expression.ConstructorResolver;
12
+import org.springframework.expression.EvaluationContext;
13
+import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
14
+
15
+final class ImplicitConstructorResolver implements
16
+        ConstructorResolver {
17
+
18
+    private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
19
+
20
+	public ConstructorExecutor resolve(final EvaluationContext context,
21
+            final String typeName, final Class<?>[] argumentTypes) throws AccessException {
22
+		try {
23
+			return delegate.resolve(context, typeName, argumentTypes);
24
+		} catch (AccessException ex) {
25
+	    	Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
26
+	    		.lookupImplicitConstructor(typeName + Arrays.toString(argumentTypes));
27
+	    	if (variable instanceof Constructor<?>) {
28
+	    		Constructor<?> constructor = (Constructor<?>) variable;
29
+				return delegate.resolve(context, constructor.getDeclaringClass().getName(), argumentTypes);
30
+	    	}
31
+	    	return null;
32
+		}
33
+    }
34
+}

+ 98
- 0
src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java View File

@@ -0,0 +1,98 @@
1
+/**
2
+ *
3
+ */
4
+package net.abhinavsarkar.spelhelper;
5
+
6
+import java.lang.reflect.Method;
7
+import java.lang.reflect.Modifier;
8
+import java.util.concurrent.ConcurrentHashMap;
9
+
10
+import org.springframework.expression.AccessException;
11
+import org.springframework.expression.EvaluationContext;
12
+import org.springframework.expression.MethodExecutor;
13
+import org.springframework.expression.MethodResolver;
14
+import org.springframework.expression.TypedValue;
15
+import org.springframework.expression.spel.support.ReflectiveMethodResolver;
16
+
17
+public final class ImplicitMethodResolver implements MethodResolver {
18
+
19
+	private static final ConcurrentHashMap<String, MethodExecutor> cache =
20
+		new ConcurrentHashMap<String, MethodExecutor>();
21
+
22
+	private static final MethodExecutor NULL_ME = new MethodExecutor() {
23
+		public TypedValue execute(final EvaluationContext context, final Object target,
24
+		        final Object... arguments) throws AccessException {
25
+			return null;
26
+		}
27
+	};
28
+
29
+	private static final class ImplicitMethodExecutor implements
30
+			MethodExecutor {
31
+		private final MethodExecutor executor;
32
+
33
+		private ImplicitMethodExecutor(final MethodExecutor executor) {
34
+			this.executor = executor;
35
+		}
36
+
37
+		public TypedValue execute(final EvaluationContext context, final Object target,
38
+				final Object... arguments) throws AccessException {
39
+			Object[] modifiedArguments = new Object[arguments.length + 1];
40
+			modifiedArguments[0] = target;
41
+			System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length);
42
+			return executor.execute(context, null, modifiedArguments);
43
+		}
44
+	}
45
+
46
+	public MethodExecutor resolve(final EvaluationContext context,
47
+			final Object targetObject, final String name, final Class<?>[] argumentTypes)
48
+			throws AccessException {
49
+		if (targetObject == null) {
50
+			return null;
51
+		}
52
+		Class<?> type = targetObject.getClass();
53
+		String cacheKey = type.getName() + "." + name;
54
+		if (cache.containsKey(cacheKey)) {
55
+			MethodExecutor executor = cache.get(cacheKey);
56
+			return executor == NULL_ME ? null : executor;
57
+		}
58
+
59
+		Method method = lookupMethod(context, type, name);
60
+		if (method != null) {
61
+			int modifiers = method.getModifiers();
62
+			if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
63
+				Class<?>[] parameterTypes = method.getParameterTypes();
64
+				Class<?> firstParameterType = parameterTypes[0];
65
+				if (parameterTypes.length > 0
66
+						&& firstParameterType.isAssignableFrom(type)) {
67
+
68
+					Class<?>[] modifiedArgumentTypes = new Class[argumentTypes.length + 1];
69
+					modifiedArgumentTypes[0] = firstParameterType;
70
+					System.arraycopy(argumentTypes, 0, modifiedArgumentTypes,
71
+							1, argumentTypes.length);
72
+					MethodExecutor executor = new ReflectiveMethodResolver()
73
+							.resolve(context, method.getDeclaringClass(), name,
74
+									modifiedArgumentTypes);
75
+					MethodExecutor wrappedExecutor = executor == null ? null
76
+							: new ImplicitMethodExecutor(executor);
77
+					cache.putIfAbsent(cacheKey, wrappedExecutor);
78
+					return wrappedExecutor;
79
+				}
80
+			}
81
+		}
82
+		cache.putIfAbsent(cacheKey, NULL_ME);
83
+		return null;
84
+	}
85
+
86
+	private static Method lookupMethod(final EvaluationContext context,
87
+			final Class<?> type, final String name) {
88
+		for (Class<?> clazz : InheritenceUtil.getInheritance(type)) {
89
+			Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
90
+				.lookupImplicitMethod(clazz.getName() + "." + name);
91
+			if (variable instanceof Method) {
92
+				return (Method) variable;
93
+			}
94
+		}
95
+		return null;
96
+	}
97
+
98
+}

+ 39
- 0
src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java View File

@@ -0,0 +1,39 @@
1
+package net.abhinavsarkar.spelhelper;
2
+
3
+import static java.util.Collections.unmodifiableList;
4
+import static java.util.Collections.unmodifiableSet;
5
+
6
+import java.util.ArrayList;
7
+import java.util.Collections;
8
+import java.util.HashSet;
9
+import java.util.List;
10
+import java.util.Set;
11
+
12
+final class ImplicitMethods {
13
+
14
+    public static <T> Set<T> distinct(final List<? extends T> list) {
15
+    	return unmodifiableSet(new HashSet<T>(list));
16
+    }
17
+
18
+    public static <T extends Comparable<? super T>> List<T> sorted(
19
+    		final List<? extends T> list) {
20
+    	List<T> temp = new ArrayList<T>(list);
21
+    	Collections.sort(temp);
22
+    	return unmodifiableList(temp);
23
+    }
24
+
25
+    public static <T> List<T> reversed(final List<? extends T> list) {
26
+    	List<T> temp = new ArrayList<T>(list);
27
+    	Collections.reverse(temp);
28
+    	return unmodifiableList(temp);
29
+    }
30
+
31
+    public static <T> List<T> take(final List<T> list, final int n) {
32
+    	return unmodifiableList(list.subList(0, n));
33
+    }
34
+
35
+    public static <T> List<T> drop(final List<T> list, final int n) {
36
+    	return unmodifiableList(list.subList(n, list.size()));
37
+    }
38
+
39
+}

+ 53
- 0
src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java View File

@@ -0,0 +1,53 @@
1
+/**
2
+ * 
3
+ */
4
+package net.abhinavsarkar.spelhelper;
5
+
6
+import java.text.MessageFormat;
7
+import java.util.concurrent.ConcurrentHashMap;
8
+
9
+import org.springframework.expression.AccessException;
10
+import org.springframework.expression.EvaluationContext;
11
+import org.springframework.expression.MethodExecutor;
12
+import org.springframework.expression.MethodResolver;
13
+import org.springframework.expression.TypedValue;
14
+import org.springframework.util.Assert;
15
+
16
+public final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
17
+	
18
+	private static final ConcurrentHashMap<String, MethodExecutor> cache =
19
+		new ConcurrentHashMap<String, MethodExecutor>();
20
+	
21
+	public boolean canRead(final EvaluationContext context,
22
+			final Object target, final String name)
23
+			throws AccessException {
24
+		Assert.notNull(target, "target is null");
25
+		String cacheKey = target.getClass().getName() + "." + name;
26
+		if (cache.containsKey(cacheKey)) {
27
+			return cache.get(cacheKey) != null;
28
+		}
29
+		
30
+		for (MethodResolver mr : context.getMethodResolvers()) {
31
+			MethodExecutor me = mr.resolve(context, target, name, new Class[0]);
32
+			if (me != null) {
33
+				cache.putIfAbsent(cacheKey, me);
34
+				return true;
35
+			}
36
+		}
37
+		
38
+		cache.putIfAbsent(cacheKey, null);
39
+		return false;
40
+	}
41
+
42
+	public TypedValue read(final EvaluationContext context,
43
+			final Object target, final String name)
44
+			throws AccessException {
45
+		if (canRead(context, target, name)) {
46
+			String cacheKey = target.getClass().getName() + "." + name;
47
+			return cache.get(cacheKey).execute(context, target, new Object[0]);
48
+		}
49
+		throw new AccessException(MessageFormat.format(
50
+				"Cannot read property: {0} of target: {1}", name, target));
51
+	}
52
+	
53
+}

+ 66
- 0
src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java View File

@@ -0,0 +1,66 @@
1
+package net.abhinavsarkar.spelhelper;
2
+
3
+import java.util.LinkedHashSet;
4
+import java.util.Set;
5
+
6
+final class InheritenceUtil {
7
+
8
+	public static Set<Class<?>> getInheritance(final Class<?> in) {
9
+		LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>();
10
+		result.add(in);
11
+		getInheritance(in, result);
12
+		return result;
13
+	}
14
+
15
+	/**
16
+	 * Get inheritance of type.
17
+	 * 
18
+	 * @param in
19
+	 * @param result
20
+	 */
21
+	private static void getInheritance(final Class<?> in, final Set<Class<?>> result) {
22
+		Class<?> superclass = getSuperclass(in);
23
+
24
+		if (superclass != null) {
25
+			result.add(superclass);
26
+			getInheritance(superclass, result);
27
+		}
28
+
29
+		getInterfaceInheritance(in, result);
30
+	}
31
+
32
+	/**
33
+	 * Get interfaces that the type inherits from.
34
+	 * 
35
+	 * @param in
36
+	 * @param result
37
+	 */
38
+	private static void getInterfaceInheritance(final Class<?> in,
39
+			final Set<Class<?>> result) {
40
+		for (Class<?> c : in.getInterfaces()) {
41
+			result.add(c);
42
+			getInterfaceInheritance(c, result);
43
+		}
44
+	}
45
+
46
+	/**
47
+	 * Get superclass of class.
48
+	 * 
49
+	 * @param in
50
+	 * @return
51
+	 */
52
+	private static Class<?> getSuperclass(final Class<?> in) {
53
+		if (in == null) {
54
+			return null;
55
+		}
56
+		if (in.isArray() && in != Object[].class) {
57
+			Class<?> type = in.getComponentType();
58
+			while (type.isArray()) {
59
+				type = type.getComponentType();
60
+			}
61
+			return type;
62
+		}
63
+		return in.getSuperclass();
64
+	}
65
+
66
+}

+ 28
- 0
src/main/java/net/abhinavsarkar/spelhelper/ReadOnlyGenericPropertyAccessor.java View File

@@ -0,0 +1,28 @@
1
+package net.abhinavsarkar.spelhelper;
2
+
3
+import java.text.MessageFormat;
4
+
5
+import org.springframework.expression.AccessException;
6
+import org.springframework.expression.EvaluationContext;
7
+import org.springframework.expression.PropertyAccessor;
8
+
9
+public abstract class ReadOnlyGenericPropertyAccessor implements
10
+		PropertyAccessor {
11
+
12
+	public final boolean canWrite(final EvaluationContext context,
13
+			final Object target, final String name) throws AccessException {
14
+		return false;
15
+	}
16
+
17
+	@SuppressWarnings("unchecked")
18
+    public final Class[] getSpecificTargetClasses() {
19
+		return null;
20
+	}
21
+
22
+	public final void write(final EvaluationContext context, final Object target,
23
+			final String name, final Object newValue) throws AccessException {
24
+		throw new AccessException(MessageFormat.format(
25
+				"Cannot write property: {0} of target: {1}", name, target));
26
+	}
27
+
28
+}

+ 143
- 0
src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java View File

@@ -0,0 +1,143 @@
1
+package net.abhinavsarkar.spelhelper;
2
+
3
+import static java.util.Arrays.asList;
4
+
5
+import java.lang.reflect.Constructor;
6
+import java.lang.reflect.Method;
7
+import java.lang.reflect.Modifier;
8
+import java.util.ArrayList;
9
+import java.util.Arrays;
10
+import java.util.HashSet;
11
+import java.util.List;
12
+import java.util.Map;
13
+import java.util.Set;
14
+import java.util.concurrent.ConcurrentHashMap;
15
+
16
+import org.springframework.expression.ConstructorResolver;
17
+import org.springframework.expression.EvaluationContext;
18
+import org.springframework.expression.ExpressionParser;
19
+import org.springframework.expression.spel.standard.SpelExpressionParser;
20
+import org.springframework.expression.spel.support.StandardEvaluationContext;
21
+import org.springframework.util.Assert;
22
+
23
+public final class SpelHelper {
24
+
25
+	public static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName();
26
+
27
+	private static final ExpressionParser PARSER = new SpelExpressionParser();
28
+	private static final ThreadLocal<EvaluationContext> currentContext =
29
+		new ThreadLocal<EvaluationContext>();
30
+
31
+	private volatile EvaluationContext context;
32
+	private final Set<Method> registeredFunctions = new HashSet<Method>();
33
+	private final Map<String,Method> registeredMethods =
34
+		new ConcurrentHashMap<String, Method>();
35
+    private final Map<String,Constructor<?>> registeredConstructors =
36
+    	new ConcurrentHashMap<String, Constructor<?>>();
37
+
38
+    {
39
+        registerFunctionsFromClass(ExtensionFunctions.class);
40
+        registerImplicitMethodsFromClass(ImplicitMethods.class);
41
+    }
42
+
43
+	public SpelHelper registerImplicitMethodsFromClass(final Class<?> clazz) {
44
+		for (Method method : filterMethods(clazz)) {
45
+			registeredMethods.put(String.format(
46
+					"%s.%s", method.getParameterTypes()[0].getName(), method.getName()),
47
+					method);
48
+		}
49
+		return this;
50
+	}
51
+
52
+    public SpelHelper registerFunctionsFromClass(final Class<?> clazz) {
53
+        registeredFunctions.addAll(filterMethods(clazz));
54
+		context = null;
55
+		return this;
56
+	}
57
+
58
+    public SpelHelper registerImplicitConstructorsFromClass(final Class<?> clazz) {
59
+    	for (Constructor<?> constructor : asList(clazz.getConstructors())) {
60
+    		registeredConstructors.put(
61
+    				constructor.getDeclaringClass().getSimpleName()
62
+                    + Arrays.toString(constructor.getParameterTypes()),
63
+                    constructor);
64
+    	}
65
+        return this;
66
+	}
67
+
68
+    public <T> T evalExpression(final String expressionString,
69
+			final Object rootElement, final Class<T> desiredType) {
70
+    	EvaluationContext evaluationContext = getEvaluationContext(rootElement);
71
+    	currentContext.set(evaluationContext);
72
+		T value = evalExpression(expressionString, evaluationContext, desiredType);
73
+		currentContext.set(null);
74
+
75
+		return value;
76
+	}
77
+
78
+	public <T> T evalExpression(final String expressionString,
79
+            final EvaluationContext evaluationContext, final Class<T> desiredType) {
80
+	    return PARSER.parseExpression(expressionString)
81
+                	.getValue(evaluationContext, desiredType);
82
+    }
83
+
84
+    public <T> T evalExpressions(final String[] expressionStrings,
85
+			final Object rootElement, final Class<T> desiredType) {
86
+        int length = expressionStrings.length;
87
+        Assert.isTrue(length > 0,
88
+                "expressionStrings should have length more than 0");
89
+        for (int i = 0; i < length - 1; i++) {
90
+            evalExpression(expressionStrings[i], rootElement, Object.class);
91
+        }
92
+		return evalExpression(expressionStrings[length - 1],
93
+                rootElement, desiredType);
94
+	}
95
+
96
+	private EvaluationContext getEvaluationContext(final Object rootObject) {
97
+		if (context == null) {
98
+			synchronized (PARSER) {
99
+				if (context == null) {
100
+					StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject);
101
+					newContext.getMethodResolvers().add(new ImplicitMethodResolver());
102
+					newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor());
103
+					newContext.setConstructorResolvers(
104
+							asList((ConstructorResolver) new ImplicitConstructorResolver()));
105
+                    for (Method method : registeredFunctions) {
106
+                    	newContext.setVariable(method.getName(), method);
107
+					}
108
+                    newContext.setVariable(CONTEXT_LOOKUP_KEY, this);
109
+                    context = newContext;
110
+				}
111
+			}
112
+		}
113
+		return context;
114
+	}
115
+
116
+	public Method lookupImplicitMethod(final String lookup) {
117
+		Assert.notNull(lookup);
118
+    	return registeredMethods.get(lookup);
119
+    }
120
+
121
+	public Constructor<?> lookupImplicitConstructor(final String lookup) {
122
+		Assert.notNull(lookup);
123
+		return registeredConstructors.get(lookup);
124
+    }
125
+
126
+	public static EvaluationContext getCurrentContext() {
127
+		return currentContext.get();
128
+	}
129
+
130
+    private static List<Method> filterMethods(final Class<?> clazz) {
131
+        List<Method> allowedMethods = new ArrayList<Method>();
132
+        for (Method method : clazz.getMethods()) {
133
+            int modifiers = method.getModifiers();
134
+            if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
135
+                    && !method.getReturnType().equals(Void.TYPE)
136
+                    && method.getParameterTypes().length > 0) {
137
+                allowedMethods.add(method);
138
+            }
139
+        }
140
+        return allowedMethods;
141
+    }
142
+
143
+}

+ 43
- 0
src/test/java/net/abhinavsarkar/spelhelper/SpelHelperTest.java View File

@@ -0,0 +1,43 @@
1
+package net.abhinavsarkar.spelhelper;
2
+
3
+import java.util.Arrays;
4
+import java.util.List;
5
+
6
+import org.junit.Assert;
7
+import org.junit.Test;
8
+
9
+public class SpelHelperTest {
10
+
11
+	@Test
12
+	public void testRegisteredFunction() {
13
+		Assert.assertEquals(
14
+				Arrays.asList("abhinav", "mini", "dan"),
15
+				new SpelHelper().evalExpression(
16
+						"#list('abhinav','mini','dan')", new Object(), List.class));
17
+	}
18
+
19
+	@Test
20
+	public void testImplicitMethod() {
21
+		Assert.assertEquals(
22
+				Arrays.asList("abhinav", "dan", "mini"),
23
+				new SpelHelper().evalExpression(
24
+						"#list('abhinav','mini','dan').sorted", new Object(), List.class));
25
+	}
26
+
27
+	public static final class ConstructorTest {
28
+		@Override
29
+		public boolean equals(final Object o) {
30
+		    return o instanceof ConstructorTest;
31
+		}
32
+	}
33
+
34
+	@Test
35
+	public void testImplicitConstructor() {
36
+		Assert.assertEquals(
37
+			new ConstructorTest(),
38
+			new SpelHelper()
39
+				.registerImplicitConstructorsFromClass(ConstructorTest.class)
40
+				.evalExpression("new ConstructorTest()", new Object(), ConstructorTest.class));
41
+	}
42
+
43
+}

Loading…
Cancel
Save