Updated to spring 3.0.6
parent
f39f6ff692
commit
9fe01a9403
|
@ -1,2 +1,4 @@
|
||||||
target/*
|
target/*
|
||||||
.pmd
|
.pmd
|
||||||
|
.scala_dependencies
|
||||||
|
.settings/
|
||||||
|
|
6
pom.xml
6
pom.xml
|
@ -19,6 +19,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<scala.version>2.7.7</scala.version>
|
<scala.version>2.7.7</scala.version>
|
||||||
|
<spring.version>3.0.6.RELEASE</spring.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<issueManagement>
|
<issueManagement>
|
||||||
|
@ -189,6 +190,7 @@
|
||||||
<groupId>org.scala-lang</groupId>
|
<groupId>org.scala-lang</groupId>
|
||||||
<artifactId>scala-library</artifactId>
|
<artifactId>scala-library</artifactId>
|
||||||
<version>${scala.version}</version>
|
<version>${scala.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.scalatest</groupId>
|
<groupId>org.scalatest</groupId>
|
||||||
|
@ -205,12 +207,12 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-core</artifactId>
|
<artifactId>spring-core</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>${spring.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-expression</artifactId>
|
<artifactId>spring-expression</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>${spring.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -1,97 +1,97 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import static java.util.Collections.unmodifiableList;
|
import static java.util.Collections.unmodifiableList;
|
||||||
import static java.util.Collections.unmodifiableMap;
|
import static java.util.Collections.unmodifiableMap;
|
||||||
import static java.util.Collections.unmodifiableSet;
|
import static java.util.Collections.unmodifiableSet;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides some extension functions to create some basic collection types
|
* Provides some extension functions to create some basic collection types
|
||||||
* inline in SpEL expressions.
|
* inline in SpEL expressions.
|
||||||
* These functions are automatically registered with {@link SpelHelper}.
|
* These functions are automatically registered with {@link SpelHelper}.
|
||||||
*
|
*
|
||||||
* **See Also:**
|
* **See Also:**
|
||||||
* [Spring Docs on extension functions](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#expressions-ref-functions)
|
* [Spring Docs on extension functions](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#expressions-ref-functions)
|
||||||
* @author Abhinav Sarkar _abhinav@abhinavsarkar.net_
|
* @author Abhinav Sarkar _abhinav@abhinavsarkar.net_
|
||||||
*/
|
*/
|
||||||
public final class ExtensionFunctions {
|
public final class ExtensionFunctions {
|
||||||
|
|
||||||
private ExtensionFunctions() {
|
private ExtensionFunctions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an unmodifiable {@link List} of the arguments provided.
|
* Creates an unmodifiable {@link List} of the arguments provided.
|
||||||
*
|
*
|
||||||
* Example use: `"#list('one', 'two', 'three')"`
|
* Example use: `"#list('one', 'two', 'three')"`
|
||||||
* @param <T> Type of the arguments provided.
|
* @param <T> Type of the arguments provided.
|
||||||
* @param args Arguments to create list of.
|
* @param args Arguments to create list of.
|
||||||
* @return An unmodifiable list of the arguments provided.
|
* @return An unmodifiable list of the arguments provided.
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> list(final T... args) {
|
public static <T> List<T> list(final T... args) {
|
||||||
return unmodifiableList(Arrays.asList(args));
|
return unmodifiableList(Arrays.asList(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an unmodifiable {@link Set} of the arguments provided.
|
* Creates an unmodifiable {@link Set} of the arguments provided.
|
||||||
*
|
*
|
||||||
* Example use: `"#set('one', 'two', 'three')"`
|
* Example use: `"#set('one', 'two', 'three')"`
|
||||||
* @param <T> Type of the arguments provided.
|
* @param <T> Type of the arguments provided.
|
||||||
* @param args Arguments to create set of.
|
* @param args Arguments to create set of.
|
||||||
* @return An unmodifiable set of the arguments provided.
|
* @return An unmodifiable set of the arguments provided.
|
||||||
*/
|
*/
|
||||||
public static <T> Set<T> set(final T... args) {
|
public static <T> Set<T> set(final T... args) {
|
||||||
return unmodifiableSet(new HashSet<T>(list(args)));
|
return unmodifiableSet(new HashSet<T>(list(args)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an unmodifiable {@link Map} using the {@link List} of keys
|
* Creates an unmodifiable {@link Map} using the {@link List} of keys
|
||||||
* provided as the first argument and the {@link List} of values provided
|
* provided as the first argument and the {@link List} of values provided
|
||||||
* as the second argument.
|
* as the second argument.
|
||||||
*
|
*
|
||||||
* Example use: `"#map(#list('one', 'two', 'three'), #list(1, 2, 3))"`
|
* Example use: `"#map(#list('one', 'two', 'three'), #list(1, 2, 3))"`
|
||||||
* @param <K> Type of the keys of the map.
|
* @param <K> Type of the keys of the map.
|
||||||
* @param <V> Type of the values of map.
|
* @param <V> Type of the values of map.
|
||||||
* @param keys List of the keys.
|
* @param keys List of the keys.
|
||||||
* @param values List of the values.
|
* @param values List of the values.
|
||||||
* @return A unmodifiable map created from the key and value lists.
|
* @return A unmodifiable map created from the key and value lists.
|
||||||
* @throws IllegalArgumentException if the number of keys and the number of
|
* @throws IllegalArgumentException if the number of keys and the number of
|
||||||
* values is not equal.
|
* values is not equal.
|
||||||
*/
|
*/
|
||||||
public static <K,V> Map<K,V> map(final List<? extends K> keys,
|
public static <K,V> Map<K,V> map(final List<? extends K> keys,
|
||||||
final List<? extends V> values) {
|
final List<? extends V> values) {
|
||||||
Assert.isTrue(keys.size() == values.size(),
|
Assert.isTrue(keys.size() == values.size(),
|
||||||
"There should be equal number of keys and values");
|
"There should be equal number of keys and values");
|
||||||
Map<K,V> map = new HashMap<K,V>();
|
Map<K,V> map = new HashMap<K,V>();
|
||||||
int length = keys.size();
|
int length = keys.size();
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
map.put(keys.get(i), values.get(i));
|
map.put(keys.get(i), values.get(i));
|
||||||
}
|
}
|
||||||
return unmodifiableMap(map);
|
return unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,52 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Arrays;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.expression.ConstructorExecutor;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.ConstructorResolver;
|
import org.springframework.expression.ConstructorExecutor;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.ConstructorResolver;
|
||||||
import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
|
||||||
final class ImplicitConstructorResolver implements
|
|
||||||
ConstructorResolver {
|
final class ImplicitConstructorResolver implements
|
||||||
|
ConstructorResolver {
|
||||||
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
|
|
||||||
|
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
|
||||||
public ConstructorExecutor resolve(final EvaluationContext context,
|
|
||||||
final String typeName, final Class<?>[] argumentTypes) throws AccessException {
|
@Override
|
||||||
try {
|
public ConstructorExecutor resolve(
|
||||||
return delegate.resolve(context, typeName, argumentTypes);
|
final EvaluationContext context, final String typeName,
|
||||||
} catch (AccessException ex) {
|
final List<TypeDescriptor> argumentTypes)
|
||||||
Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
|
throws AccessException {
|
||||||
.lookupImplicitConstructor(typeName + Arrays.toString(argumentTypes));
|
try {
|
||||||
if (variable instanceof Constructor<?>) {
|
return delegate.resolve(context, typeName, argumentTypes);
|
||||||
Constructor<?> constructor = (Constructor<?>) variable;
|
} catch (AccessException ex) {
|
||||||
return delegate.resolve(context, constructor.getDeclaringClass().getName(), argumentTypes);
|
Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
|
||||||
}
|
.lookupImplicitConstructor(typeName + argumentTypes.toString());
|
||||||
return null;
|
if (variable instanceof Constructor<?>) {
|
||||||
}
|
Constructor<?> constructor = (Constructor<?>) variable;
|
||||||
}
|
return delegate.resolve(context, constructor.getDeclaringClass().getName(), argumentTypes);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,113 +1,120 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import org.springframework.expression.AccessException;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.MethodExecutor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.expression.MethodResolver;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.TypedValue;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.spel.support.ReflectiveMethodResolver;
|
import org.springframework.expression.MethodExecutor;
|
||||||
|
import org.springframework.expression.MethodResolver;
|
||||||
final class ImplicitMethodResolver implements MethodResolver {
|
import org.springframework.expression.TypedValue;
|
||||||
|
import org.springframework.expression.spel.support.ReflectiveMethodResolver;
|
||||||
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
|
||||||
new ConcurrentHashMap<String, MethodExecutor>();
|
final class ImplicitMethodResolver implements MethodResolver {
|
||||||
|
|
||||||
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
||||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
new ConcurrentHashMap<String, MethodExecutor>();
|
||||||
final Object... arguments) throws AccessException {
|
|
||||||
return null;
|
private final ReflectiveMethodResolver delegate = new ReflectiveMethodResolver();
|
||||||
}
|
|
||||||
};
|
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
||||||
|
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||||
private static final class ImplicitMethodExecutor implements
|
final Object... arguments) throws AccessException {
|
||||||
MethodExecutor {
|
return null;
|
||||||
private final MethodExecutor executor;
|
}
|
||||||
|
};
|
||||||
public ImplicitMethodExecutor(final MethodExecutor executor) {
|
|
||||||
this.executor = executor;
|
private static final class ImplicitMethodExecutor implements
|
||||||
}
|
MethodExecutor {
|
||||||
|
private final MethodExecutor executor;
|
||||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
|
||||||
final Object... arguments) throws AccessException {
|
public ImplicitMethodExecutor(final MethodExecutor executor) {
|
||||||
Object[] modifiedArguments = new Object[arguments.length + 1];
|
this.executor = executor;
|
||||||
modifiedArguments[0] = target;
|
}
|
||||||
System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length);
|
|
||||||
return executor.execute(context, null, modifiedArguments);
|
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||||
}
|
final Object... arguments) throws AccessException {
|
||||||
}
|
Object[] modifiedArguments = new Object[arguments.length + 1];
|
||||||
|
modifiedArguments[0] = target;
|
||||||
public MethodExecutor resolve(final EvaluationContext context,
|
System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length);
|
||||||
final Object targetObject, final String name, final Class<?>[] argumentTypes)
|
return executor.execute(context, null, modifiedArguments);
|
||||||
throws AccessException {
|
}
|
||||||
if (targetObject == null) {
|
}
|
||||||
return null;
|
|
||||||
}
|
@Override
|
||||||
Class<?> type = targetObject.getClass();
|
public MethodExecutor resolve(
|
||||||
String cacheKey = type.getName() + "." + name;
|
final EvaluationContext context, final Object targetObject,
|
||||||
if (CACHE.containsKey(cacheKey)) {
|
final String name, final List<TypeDescriptor> argumentTypes)
|
||||||
MethodExecutor executor = CACHE.get(cacheKey);
|
throws AccessException {
|
||||||
return executor == NULL_ME ? null : executor;
|
if (targetObject == null) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
Method method = lookupMethod(context, type, name);
|
Class<?> type = targetObject.getClass();
|
||||||
if (method != null) {
|
String cacheKey = type.getName() + "." + name;
|
||||||
int modifiers = method.getModifiers();
|
if (CACHE.containsKey(cacheKey)) {
|
||||||
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
|
MethodExecutor executor = CACHE.get(cacheKey);
|
||||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
return executor == NULL_ME ? null : executor;
|
||||||
Class<?> firstParamType = parameterTypes[0];
|
}
|
||||||
if (parameterTypes.length > 0
|
|
||||||
&& firstParamType.isAssignableFrom(type)) {
|
Method method = lookupMethod(context, type, name);
|
||||||
Class<?>[] newArgumentTypes = new Class[argumentTypes.length + 1];
|
if (method != null) {
|
||||||
newArgumentTypes[0] = firstParamType;
|
int modifiers = method.getModifiers();
|
||||||
System.arraycopy(argumentTypes, 0, newArgumentTypes,
|
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
|
||||||
1, argumentTypes.length);
|
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||||
MethodExecutor executor = new ReflectiveMethodResolver()
|
Class<?> firstParamType = parameterTypes[0];
|
||||||
.resolve(context, method.getDeclaringClass(), name,
|
if (parameterTypes.length > 0
|
||||||
newArgumentTypes);
|
&& firstParamType.isAssignableFrom(type)) {
|
||||||
MethodExecutor wrappedExecutor = executor == null ? null
|
List<TypeDescriptor> newArgumentTypes = new ArrayList<TypeDescriptor>();
|
||||||
: new ImplicitMethodExecutor(executor);
|
newArgumentTypes.add(TypeDescriptor.valueOf(firstParamType));
|
||||||
if (wrappedExecutor == null) {
|
newArgumentTypes.addAll(argumentTypes);
|
||||||
CACHE.putIfAbsent(cacheKey, NULL_ME);
|
|
||||||
}
|
MethodExecutor executor =
|
||||||
return wrappedExecutor;
|
delegate.resolve(context, method.getDeclaringClass(),
|
||||||
}
|
name, newArgumentTypes);
|
||||||
}
|
MethodExecutor wrappedExecutor = executor == null ? null
|
||||||
}
|
: new ImplicitMethodExecutor(executor);
|
||||||
CACHE.putIfAbsent(cacheKey, NULL_ME);
|
if (wrappedExecutor == null) {
|
||||||
return null;
|
CACHE.putIfAbsent(cacheKey, NULL_ME);
|
||||||
}
|
}
|
||||||
|
return wrappedExecutor;
|
||||||
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))
|
CACHE.putIfAbsent(cacheKey, NULL_ME);
|
||||||
.lookupImplicitMethod(clazz.getName() + "." + name);
|
return null;
|
||||||
if (variable instanceof Method) {
|
}
|
||||||
return (Method) variable;
|
|
||||||
}
|
private static Method lookupMethod(final EvaluationContext context,
|
||||||
}
|
final Class<?> type, final String name) {
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,129 +1,129 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import static java.util.Collections.unmodifiableList;
|
import static java.util.Collections.unmodifiableList;
|
||||||
import static java.util.Collections.unmodifiableSet;
|
import static java.util.Collections.unmodifiableSet;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides some implicit methods which can be invoked on the instances of
|
* Provides some implicit methods which can be invoked on the instances of
|
||||||
* class of the first parameter of the method inside a SpEL expression.
|
* class of the first parameter of the method inside a SpEL expression.
|
||||||
* @author Abhinav Sarkar _abhinav@abhinavsarkar.net_
|
* @author Abhinav Sarkar _abhinav@abhinavsarkar.net_
|
||||||
*/
|
*/
|
||||||
public final class ImplicitMethods {
|
public final class ImplicitMethods {
|
||||||
|
|
||||||
private ImplicitMethods() {
|
private ImplicitMethods() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides implicit method `distinct` on the {@link List} class.
|
* Provides implicit method `distinct` on the {@link List} class.
|
||||||
*
|
*
|
||||||
* Example: `"#list('a','b','a').distinct()" //should return List('a','b')`
|
* Example: `"#list('a','b','a').distinct()" //should return List('a','b')`
|
||||||
*
|
*
|
||||||
* With implicit property support provided by {@link SpelHelper} this can
|
* With implicit property support provided by {@link SpelHelper} this can
|
||||||
* also be written as:
|
* also be written as:
|
||||||
*
|
*
|
||||||
* `"#list('a','b','a').distinct" //same output as earlier`
|
* `"#list('a','b','a').distinct" //same output as earlier`
|
||||||
* @param <T> Type of the list's elements.
|
* @param <T> Type of the list's elements.
|
||||||
* @param list The list to call this method upon.
|
* @param list The list to call this method upon.
|
||||||
* @return An unmodifiable {@link Set} containing the distinct items of the list.
|
* @return An unmodifiable {@link Set} containing the distinct items of the list.
|
||||||
*/
|
*/
|
||||||
public static <T> Set<T> distinct(final List<? extends T> list) {
|
public static <T> Set<T> distinct(final List<? extends T> list) {
|
||||||
return unmodifiableSet(new HashSet<T>(list));
|
return unmodifiableSet(new HashSet<T>(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides implicit method `sorted` on the {@link List} class.
|
* Provides implicit method `sorted` on the {@link List} class.
|
||||||
*
|
*
|
||||||
* Example: `"#list('c','b','a').sorted()" //should return List('a','b','c')`
|
* Example: `"#list('c','b','a').sorted()" //should return List('a','b','c')`
|
||||||
*
|
*
|
||||||
* With implicit property support provided by {@link SpelHelper} this can
|
* With implicit property support provided by {@link SpelHelper} this can
|
||||||
* also be written as:
|
* also be written as:
|
||||||
*
|
*
|
||||||
* `"#list('c','b','a').sorted" //same output as earlier`
|
* `"#list('c','b','a').sorted" //same output as earlier`
|
||||||
* @param <T> Type of the list's elements.
|
* @param <T> Type of the list's elements.
|
||||||
* @param list The list to call this method upon.
|
* @param list The list to call this method upon.
|
||||||
* @return An unmodifiable {@link List} containing the sorted items
|
* @return An unmodifiable {@link List} containing the sorted items
|
||||||
* of the list.
|
* of the list.
|
||||||
* @see Collections#sort(List)
|
* @see Collections#sort(List)
|
||||||
*/
|
*/
|
||||||
public static <T extends Comparable<? super T>> List<T> sorted(
|
public static <T extends Comparable<? super T>> List<T> sorted(
|
||||||
final List<? extends T> list) {
|
final List<? extends T> list) {
|
||||||
List<T> temp = new ArrayList<T>(list);
|
List<T> temp = new ArrayList<T>(list);
|
||||||
Collections.sort(temp);
|
Collections.sort(temp);
|
||||||
return unmodifiableList(temp);
|
return unmodifiableList(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides implicit method `reversed` on the {@link List} class.
|
* Provides implicit method `reversed` on the {@link List} class.
|
||||||
*
|
*
|
||||||
* Example: `"#list('c','b','a').reversed()" //should return List('a','b','c')`
|
* Example: `"#list('c','b','a').reversed()" //should return List('a','b','c')`
|
||||||
*
|
*
|
||||||
* With implicit property support provided by {@link SpelHelper} this can
|
* With implicit property support provided by {@link SpelHelper} this can
|
||||||
* also be written as:
|
* also be written as:
|
||||||
*
|
*
|
||||||
* `"#list('c','b','a').reversed" //same output as earlier`
|
* `"#list('c','b','a').reversed" //same output as earlier`
|
||||||
* @param <T> Type of the list's elements.
|
* @param <T> Type of the list's elements.
|
||||||
* @param list The list to call this method upon.
|
* @param list The list to call this method upon.
|
||||||
* @return An unmodifiable {@link List} containing the items of the
|
* @return An unmodifiable {@link List} containing the items of the
|
||||||
* list in reverse order.
|
* list in reverse order.
|
||||||
* @see Collections#reverse(List)
|
* @see Collections#reverse(List)
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> reversed(final List<? extends T> list) {
|
public static <T> List<T> reversed(final List<? extends T> list) {
|
||||||
List<T> temp = new ArrayList<T>(list);
|
List<T> temp = new ArrayList<T>(list);
|
||||||
Collections.reverse(temp);
|
Collections.reverse(temp);
|
||||||
return unmodifiableList(temp);
|
return unmodifiableList(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides implicit method `take` on the {@link List} class.
|
* Provides implicit method `take` on the {@link List} class.
|
||||||
*
|
*
|
||||||
* Example: `"#list('c','b','a').take(2)" //should return List('a','b')`
|
* Example: `"#list('c','b','a').take(2)" //should return List('a','b')`
|
||||||
*
|
*
|
||||||
* @param <T> Type of the list's elements.
|
* @param <T> Type of the list's elements.
|
||||||
* @param list The list to call this method upon.
|
* @param list The list to call this method upon.
|
||||||
* @param n Number of items to _take_ from the list.
|
* @param n Number of items to _take_ from the list.
|
||||||
* @return An unmodifiable {@link List} containing the first `n` items
|
* @return An unmodifiable {@link List} containing the first `n` items
|
||||||
* of the list.
|
* of the list.
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> take(final List<T> list, final int n) {
|
public static <T> List<T> take(final List<T> list, final int n) {
|
||||||
return unmodifiableList(list.subList(0, n));
|
return unmodifiableList(list.subList(0, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides implicit method `drop` on the {@link List} class.
|
* Provides implicit method `drop` on the {@link List} class.
|
||||||
*
|
*
|
||||||
* Example: `"#list('c','b','a').drop(2)" //should return List('a')`
|
* Example: `"#list('c','b','a').drop(2)" //should return List('a')`
|
||||||
*
|
*
|
||||||
* @param <T> Type of the list's elements.
|
* @param <T> Type of the list's elements.
|
||||||
* @param list The list to call this method upon.
|
* @param list The list to call this method upon.
|
||||||
* @param n Number of items to _drop_ from the list.
|
* @param n Number of items to _drop_ from the list.
|
||||||
* @return An unmodifiable {@link List} containing the items after the
|
* @return An unmodifiable {@link List} containing the items after the
|
||||||
* first `n` items of the list.
|
* first `n` items of the list.
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> drop(final List<T> list, final int n) {
|
public static <T> List<T> drop(final List<T> list, final int n) {
|
||||||
return unmodifiableList(list.subList(n, list.size()));
|
return unmodifiableList(list.subList(n, list.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +1,70 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.springframework.expression.AccessException;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.expression.MethodExecutor;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.MethodResolver;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.TypedValue;
|
import org.springframework.expression.MethodExecutor;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.expression.MethodResolver;
|
||||||
|
import org.springframework.expression.TypedValue;
|
||||||
final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
||||||
new ConcurrentHashMap<String, MethodExecutor>();
|
|
||||||
|
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
||||||
public boolean canRead(final EvaluationContext context,
|
new ConcurrentHashMap<String, MethodExecutor>();
|
||||||
final Object target, final String name)
|
|
||||||
throws AccessException {
|
public boolean canRead(final EvaluationContext context,
|
||||||
Assert.notNull(target, "target is null");
|
final Object target, final String name)
|
||||||
String cacheKey = target.getClass().getName() + "." + name;
|
throws AccessException {
|
||||||
if (CACHE.containsKey(cacheKey)) {
|
Assert.notNull(target, "target is null");
|
||||||
return CACHE.get(cacheKey) != 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) {
|
for (MethodResolver mr : context.getMethodResolvers()) {
|
||||||
CACHE.putIfAbsent(cacheKey, me);
|
MethodExecutor me =
|
||||||
return true;
|
mr.resolve(context, target, name, Collections.<TypeDescriptor>emptyList());
|
||||||
}
|
if (me != null) {
|
||||||
}
|
CACHE.putIfAbsent(cacheKey, me);
|
||||||
|
return true;
|
||||||
CACHE.putIfAbsent(cacheKey, null);
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
CACHE.putIfAbsent(cacheKey, null);
|
||||||
public TypedValue read(final EvaluationContext context,
|
return false;
|
||||||
final Object target, final String name)
|
}
|
||||||
throws AccessException {
|
|
||||||
if (canRead(context, target, name)) {
|
public TypedValue read(final EvaluationContext context,
|
||||||
String cacheKey = target.getClass().getName() + "." + name;
|
final Object target, final String name)
|
||||||
return CACHE.get(cacheKey).execute(context, target, new Object[0]);
|
throws AccessException {
|
||||||
}
|
if (canRead(context, target, name)) {
|
||||||
throw new AccessException(MessageFormat.format(
|
String cacheKey = target.getClass().getName() + "." + name;
|
||||||
"Cannot read property: {0} of target: {1}", name, target));
|
return CACHE.get(cacheKey).execute(context, target, new Object[0]);
|
||||||
}
|
}
|
||||||
|
throw new AccessException(MessageFormat.format(
|
||||||
|
"Cannot read property: {0} of target: {1}", name, target));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,86 +1,86 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
final class InheritenceUtil {
|
final class InheritenceUtil {
|
||||||
|
|
||||||
private InheritenceUtil() {
|
private InheritenceUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Class<?>> getInheritance(final Class<?> clazz) {
|
public static Set<Class<?>> getInheritance(final Class<?> clazz) {
|
||||||
LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>();
|
LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>();
|
||||||
result.add(clazz);
|
result.add(clazz);
|
||||||
getInheritance(clazz, result);
|
getInheritance(clazz, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get inheritance of type.
|
* Get inheritance of type.
|
||||||
*
|
*
|
||||||
* @param clazz
|
* @param clazz
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
private static void getInheritance(final Class<?> clazz, final Set<Class<?>> result) {
|
private static void getInheritance(final Class<?> clazz, final Set<Class<?>> result) {
|
||||||
Class<?> superclass = getSuperclass(clazz);
|
Class<?> superclass = getSuperclass(clazz);
|
||||||
|
|
||||||
if (superclass != null) {
|
if (superclass != null) {
|
||||||
result.add(superclass);
|
result.add(superclass);
|
||||||
getInheritance(superclass, result);
|
getInheritance(superclass, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
getInterfaceInheritance(clazz, result);
|
getInterfaceInheritance(clazz, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get interfaces that the type inherits from.
|
* Get interfaces that the type inherits from.
|
||||||
*
|
*
|
||||||
* @param clazz
|
* @param clazz
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
private static void getInterfaceInheritance(final Class<?> clazz,
|
private static void getInterfaceInheritance(final Class<?> clazz,
|
||||||
final Set<Class<?>> result) {
|
final Set<Class<?>> result) {
|
||||||
for (Class<?> c : clazz.getInterfaces()) {
|
for (Class<?> c : clazz.getInterfaces()) {
|
||||||
result.add(c);
|
result.add(c);
|
||||||
getInterfaceInheritance(c, result);
|
getInterfaceInheritance(c, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get superclass of class.
|
* Get superclass of class.
|
||||||
*
|
*
|
||||||
* @param clazz
|
* @param clazz
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static Class<?> getSuperclass(final Class<?> clazz) {
|
private static Class<?> getSuperclass(final Class<?> clazz) {
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (clazz.isArray() && clazz != Object[].class) {
|
if (clazz.isArray() && clazz != Object[].class) {
|
||||||
Class<?> type = clazz.getComponentType();
|
Class<?> type = clazz.getComponentType();
|
||||||
while (type.isArray()) {
|
while (type.isArray()) {
|
||||||
type = type.getComponentType();
|
type = type.getComponentType();
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
return clazz.getSuperclass();
|
return clazz.getSuperclass();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.PropertyAccessor;
|
import org.springframework.expression.PropertyAccessor;
|
||||||
|
|
||||||
abstract class ReadOnlyGenericPropertyAccessor implements
|
abstract class ReadOnlyGenericPropertyAccessor implements
|
||||||
PropertyAccessor {
|
PropertyAccessor {
|
||||||
|
|
||||||
public final boolean canWrite(final EvaluationContext context,
|
public final boolean canWrite(final EvaluationContext context,
|
||||||
final Object target, final String name) throws AccessException {
|
final Object target, final String name) throws AccessException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public final Class[] getSpecificTargetClasses() {
|
public final Class[] getSpecificTargetClasses() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void write(final EvaluationContext context, final Object target,
|
public final void write(final EvaluationContext context, final Object target,
|
||||||
final String name, final Object newValue) throws AccessException {
|
final String name, final Object newValue) throws AccessException {
|
||||||
throw new AccessException(MessageFormat.format(
|
throw new AccessException(MessageFormat.format(
|
||||||
"Cannot write property: {0} of target: {1}", name, target));
|
"Cannot write property: {0} of target: {1}", name, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,349 +1,349 @@
|
||||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net>
|
||||||
*
|
*
|
||||||
* This file is a part of SpelHelper library.
|
* This file is a part of SpelHelper library.
|
||||||
*
|
*
|
||||||
* SpelHelper library is free software: you can redistribute it and/or modify
|
* SpelHelper library is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
* it under the terms of the GNU Lesser General Public License (GNU LGPL) as
|
||||||
* published by the Free Software Foundation, either version 3 of the License,
|
* published by the Free Software Foundation, either version 3 of the License,
|
||||||
* or (at your option) any later version.
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* SpelHelper library is distributed in the hope that it will be useful,
|
* SpelHelper library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
* along with SpelHelper library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.springframework.expression.ConstructorResolver;
|
import org.springframework.expression.ConstructorResolver;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.ExpressionParser;
|
import org.springframework.expression.ExpressionParser;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SpelHelper provides additional functionalities to work with
|
* SpelHelper provides additional functionalities to work with
|
||||||
* [Spring Expression Language (SpEL)][1].
|
* [Spring Expression Language (SpEL)][1].
|
||||||
*
|
*
|
||||||
* The addition functionalities provided are:
|
* The addition functionalities provided are:
|
||||||
*
|
*
|
||||||
* 1. Implicit methods
|
* 1. Implicit methods
|
||||||
* 2. Implicit properties
|
* 2. Implicit properties
|
||||||
* 3. Simplified extension functions
|
* 3. Simplified extension functions
|
||||||
* 4. Simplified constructors
|
* 4. Simplified constructors
|
||||||
*
|
*
|
||||||
* **Implicit Methods**
|
* **Implicit Methods**
|
||||||
*
|
*
|
||||||
* Implicit methods allow one to registers methods with SpelHelper and attach
|
* Implicit methods allow one to registers methods with SpelHelper and attach
|
||||||
* them to particular classes. After that, when that method is called on an
|
* them to particular classes. After that, when that method is called on an
|
||||||
* object of that particular class inside a SpEL expression, SpelHelper
|
* object of that particular class inside a SpEL expression, SpelHelper
|
||||||
* redirects the method call to the registered method.
|
* redirects the method call to the registered method.
|
||||||
*
|
*
|
||||||
* Example: {@link ImplicitMethods#sorted(List)} method is automatically
|
* Example: {@link ImplicitMethods#sorted(List)} method is automatically
|
||||||
* registered by SpelHelper. The class that the method should be invoked for
|
* registered by SpelHelper. The class that the method should be invoked for
|
||||||
* is the type of the first parameter of the method. In this case, the class is
|
* is the type of the first parameter of the method. In this case, the class is
|
||||||
* {@link List}.
|
* {@link List}.
|
||||||
*
|
*
|
||||||
* So when an expression like `"#list(1,4,2).sorted()"` is evaluated, the
|
* So when an expression like `"#list(1,4,2).sorted()"` is evaluated, the
|
||||||
* {@link ImplicitMethods#sorted(List)} method is invoked with the list as its
|
* {@link ImplicitMethods#sorted(List)} method is invoked with the list as its
|
||||||
* first parameter and its return value is used in further evaluation of the
|
* first parameter and its return value is used in further evaluation of the
|
||||||
* expression.
|
* expression.
|
||||||
*
|
*
|
||||||
* See {@link SpelHelper#registerImplicitMethodsFromClass(Class)}.
|
* See {@link SpelHelper#registerImplicitMethodsFromClass(Class)}.
|
||||||
*
|
*
|
||||||
* **Implicit Properties**
|
* **Implicit Properties**
|
||||||
*
|
*
|
||||||
* Implicit properties allow one to treat no argument methods of an object
|
* Implicit properties allow one to treat no argument methods of an object
|
||||||
* as properties of the object. SpelHelper intercepts the property resolution
|
* as properties of the object. SpelHelper intercepts the property resolution
|
||||||
* of SpEL and if the property name is same as some no-arg method of the target
|
* of SpEL and if the property name is same as some no-arg method of the target
|
||||||
* object then it invokes the method on the object and provides its return value
|
* object then it invokes the method on the object and provides its return value
|
||||||
* as the property value for further evaluation of the expression.
|
* as the property value for further evaluation of the expression.
|
||||||
*
|
*
|
||||||
* Example: Using implicit properties, the example of implicit methods can be
|
* Example: Using implicit properties, the example of implicit methods can be
|
||||||
* written as: `"#list(1,4,2).sorted"` - dropping the parens - and it will return
|
* written as: `"#list(1,4,2).sorted"` - dropping the parens - and it will return
|
||||||
* the same value as the last example.
|
* the same value as the last example.
|
||||||
*
|
*
|
||||||
* Implicit property resolution considers both the actual methods of the object
|
* Implicit property resolution considers both the actual methods of the object
|
||||||
* and the implicit methods registered on the object's class.
|
* and the implicit methods registered on the object's class.
|
||||||
*
|
*
|
||||||
* **Simplified extension functions**
|
* **Simplified extension functions**
|
||||||
*
|
*
|
||||||
* SpEL [allows][2] to register extension function on the context by providing a
|
* SpEL [allows][2] to register extension function on the context by providing a
|
||||||
* name and a {@link Method} object. SpelHelper simplifies this by taking a class
|
* name and a {@link Method} object. SpelHelper simplifies this by taking a class
|
||||||
* and registering all the `public static` methods of the class which do not
|
* and registering all the `public static` methods of the class which do not
|
||||||
* have a `void` return type. The methods are registered by their simple name.
|
* have a `void` return type. The methods are registered by their simple name.
|
||||||
*
|
*
|
||||||
* Example: All the methods of {@link ExtensionFunctions} class are automatically
|
* Example: All the methods of {@link ExtensionFunctions} class are automatically
|
||||||
* registered by SpelHelper. Hence the method {@link ExtensionFunctions#list(Object...)}
|
* registered by SpelHelper. Hence the method {@link ExtensionFunctions#list(Object...)}
|
||||||
* can be called from inside a SpEL expression using the function call syntax:
|
* can be called from inside a SpEL expression using the function call syntax:
|
||||||
* `"#list(1,2,3)`".
|
* `"#list(1,2,3)`".
|
||||||
*
|
*
|
||||||
* See {@link SpelHelper#registerFunctionsFromClass(Class)}.
|
* See {@link SpelHelper#registerFunctionsFromClass(Class)}.
|
||||||
*
|
*
|
||||||
* **Simplified constructors**
|
* **Simplified constructors**
|
||||||
*
|
*
|
||||||
* SpEL [allows][3] calling constructors from inside a SpEL expression using the
|
* SpEL [allows][3] calling constructors from inside a SpEL expression using the
|
||||||
* `new` operator. But they have to be called with their full name like:
|
* `new` operator. But they have to be called with their full name like:
|
||||||
* `"new org.example.Foo('bar')"`. SpelHelper simplifies this by taking a class
|
* `"new org.example.Foo('bar')"`. SpelHelper simplifies this by taking a class
|
||||||
* and registering all its public constructors to the SpEL context by their
|
* and registering all its public constructors to the SpEL context by their
|
||||||
* simple name.
|
* simple name.
|
||||||
*
|
*
|
||||||
* Example: After registering the `org.example.Foo` class with SpelHelper, its
|
* Example: After registering the `org.example.Foo` class with SpelHelper, its
|
||||||
* constructor can be called from inside a SpEL expression by: `"new Foo('bar')"`.
|
* constructor can be called from inside a SpEL expression by: `"new Foo('bar')"`.
|
||||||
*
|
*
|
||||||
* See {@link SpelHelper#registerConstructorsFromClass(Class)}.
|
* See {@link SpelHelper#registerConstructorsFromClass(Class)}.
|
||||||
*
|
*
|
||||||
* In addition to all the above functionalities, SpelHelper automatically registers
|
* In addition to all the above functionalities, SpelHelper automatically registers
|
||||||
* some extension functions and implicit methods which are always available in
|
* some extension functions and implicit methods which are always available in
|
||||||
* the SpEL expressions evaluated through SpelHelper. See {@link ExtensionFunctions}
|
* the SpEL expressions evaluated through SpelHelper. See {@link ExtensionFunctions}
|
||||||
* and {@link ImplicitMethods} for further details.
|
* and {@link ImplicitMethods} for further details.
|
||||||
*
|
*
|
||||||
* [1]: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html
|
* [1]: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html
|
||||||
* [2]: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#expressions-ref-functions
|
* [2]: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#expressions-ref-functions
|
||||||
* [3]: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#d0e11927
|
* [3]: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#d0e11927
|
||||||
*
|
*
|
||||||
* @author Abhinav Sarkar _abhinav@abhinavsarkar.net_
|
* @author Abhinav Sarkar _abhinav@abhinavsarkar.net_
|
||||||
*/
|
*/
|
||||||
public final class SpelHelper {
|
public final class SpelHelper {
|
||||||
|
|
||||||
static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName();
|
static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName();
|
||||||
|
|
||||||
private final ExpressionParser PARSER = new SpelExpressionParser();
|
private final ExpressionParser PARSER = new SpelExpressionParser();
|
||||||
private static final ThreadLocal<EvaluationContext> CURRENT_CONTEXT =
|
private static final ThreadLocal<EvaluationContext> CURRENT_CONTEXT =
|
||||||
new ThreadLocal<EvaluationContext>();
|
new ThreadLocal<EvaluationContext>();
|
||||||
|
|
||||||
private final Set<Method> registeredFunctions = new HashSet<Method>();
|
private final Set<Method> registeredFunctions = new HashSet<Method>();
|
||||||
private final Map<String,Method> registeredMethods =
|
private final Map<String,Method> registeredMethods =
|
||||||
new ConcurrentHashMap<String, Method>();
|
new ConcurrentHashMap<String, Method>();
|
||||||
private final Map<String,Constructor<?>> registeredConstructors =
|
private final Map<String,Constructor<?>> registeredConstructors =
|
||||||
new ConcurrentHashMap<String, Constructor<?>>();
|
new ConcurrentHashMap<String, Constructor<?>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of SpelHelper.
|
* Creates an instance of SpelHelper.
|
||||||
*/
|
*/
|
||||||
public SpelHelper() {
|
public SpelHelper() {
|
||||||
registerFunctionsFromClass(ExtensionFunctions.class);
|
registerFunctionsFromClass(ExtensionFunctions.class);
|
||||||
registerImplicitMethodsFromClass(ImplicitMethods.class);
|
registerImplicitMethodsFromClass(ImplicitMethods.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the public static methods in the class `clazz` as implicit
|
* Registers the public static methods in the class `clazz` as implicit
|
||||||
* methods for the class of the first parameter of the methods.
|
* methods for the class of the first parameter of the methods.
|
||||||
*
|
*
|
||||||
* Only registers the public static methods with non void return type and at
|
* Only registers the public static methods with non void return type and at
|
||||||
* least one argument.
|
* least one argument.
|
||||||
* @see ImplicitMethods
|
* @see ImplicitMethods
|
||||||
* @param clazz The class to register the methods from.
|
* @param clazz The class to register the methods from.
|
||||||
* @return The current instance of SpelHelper. This is for chaining
|
* @return The current instance of SpelHelper. This is for chaining
|
||||||
* the methods calls.
|
* the methods calls.
|
||||||
*/
|
*/
|
||||||
public SpelHelper registerImplicitMethodsFromClass(final Class<?> clazz) {
|
public SpelHelper registerImplicitMethodsFromClass(final Class<?> clazz) {
|
||||||
for (Method method : filterMethods(clazz)) {
|
for (Method method : filterMethods(clazz)) {
|
||||||
registeredMethods.put(String.format(
|
registeredMethods.put(String.format(
|
||||||
"%s.%s", method.getParameterTypes()[0].getName(), method.getName()),
|
"%s.%s", method.getParameterTypes()[0].getName(), method.getName()),
|
||||||
method);
|
method);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the public static methods in the class `clazz` as functions
|
* Registers the public static methods in the class `clazz` as functions
|
||||||
* which can be called from SpEL expressions.
|
* which can be called from SpEL expressions.
|
||||||
* The functions are registered with the simple name of the methods.
|
* The functions are registered with the simple name of the methods.
|
||||||
*
|
*
|
||||||
* Only registers the public static methods with non void return type.
|
* Only registers the public static methods with non void return type.
|
||||||
* @see ExtensionFunctions
|
* @see ExtensionFunctions
|
||||||
* @param clazz The class to register the functions from.
|
* @param clazz The class to register the functions from.
|
||||||
* @return The current instance of SpelHelper. This is for chaining
|
* @return The current instance of SpelHelper. This is for chaining
|
||||||
* the methods calls.
|
* the methods calls.
|
||||||
*/
|
*/
|
||||||
public SpelHelper registerFunctionsFromClass(final Class<?> clazz) {
|
public SpelHelper registerFunctionsFromClass(final Class<?> clazz) {
|
||||||
registeredFunctions.addAll(filterFunctions(clazz));
|
registeredFunctions.addAll(filterFunctions(clazz));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the public constructors of the class `clazz` so that they
|
* Registers the public constructors of the class `clazz` so that they
|
||||||
* can be called by their simple name from SpEL expressions.
|
* can be called by their simple name from SpEL expressions.
|
||||||
* @param clazz The class to register the constructors from.
|
* @param clazz The class to register the constructors from.
|
||||||
* @return The current instance of SpelHelper. This is for chaining
|
* @return The current instance of SpelHelper. This is for chaining
|
||||||
* the methods calls.
|
* the methods calls.
|
||||||
*/
|
*/
|
||||||
public SpelHelper registerConstructorsFromClass(final Class<?> clazz) {
|
public SpelHelper registerConstructorsFromClass(final Class<?> clazz) {
|
||||||
for (Constructor<?> constructor : asList(clazz.getConstructors())) {
|
for (Constructor<?> constructor : asList(clazz.getConstructors())) {
|
||||||
registeredConstructors.put(
|
registeredConstructors.put(
|
||||||
constructor.getDeclaringClass().getSimpleName()
|
constructor.getDeclaringClass().getSimpleName()
|
||||||
+ Arrays.toString(constructor.getParameterTypes()),
|
+ Arrays.toString(constructor.getParameterTypes()),
|
||||||
constructor);
|
constructor);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a SpEL expression `expressionString` in the context
|
* Evaluates a SpEL expression `expressionString` in the context
|
||||||
* of root element `rootElement` and gives back a result of type
|
* of root element `rootElement` and gives back a result of type
|
||||||
* `desiredType`.
|
* `desiredType`.
|
||||||
* @param <T> The type of the result desired.
|
* @param <T> The type of the result desired.
|
||||||
* @param expressionString The SpEL expression to evaluate.
|
* @param expressionString The SpEL expression to evaluate.
|
||||||
* @param rootElement The root element in context of which the expression
|
* @param rootElement The root element in context of which the expression
|
||||||
* is to be evaluated.
|
* is to be evaluated.
|
||||||
* @param desiredType The class of the result desired.
|
* @param desiredType The class of the result desired.
|
||||||
* @return The result of the evaluation of the expression.
|
* @return The result of the evaluation of the expression.
|
||||||
* @see ExpressionParser#parseExpression(String)
|
* @see ExpressionParser#parseExpression(String)
|
||||||
* @see Expression#getValue(EvaluationContext, Class)
|
* @see Expression#getValue(EvaluationContext, Class)
|
||||||
*/
|
*/
|
||||||
public <T> T evalExpression(final String expressionString,
|
public <T> T evalExpression(final String expressionString,
|
||||||
final Object rootElement, final Class<T> desiredType) {
|
final Object rootElement, final Class<T> desiredType) {
|
||||||
EvaluationContext evaluationContext = getEvaluationContext(rootElement);
|
EvaluationContext evaluationContext = getEvaluationContext(rootElement);
|
||||||
CURRENT_CONTEXT.set(evaluationContext);
|
CURRENT_CONTEXT.set(evaluationContext);
|
||||||
T value = evalExpression(expressionString, evaluationContext, desiredType);
|
T value = evalExpression(expressionString, evaluationContext, desiredType);
|
||||||
CURRENT_CONTEXT.set(null);
|
CURRENT_CONTEXT.set(null);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a SpEL expression `expressionString` in the provided
|
* Evaluates a SpEL expression `expressionString` in the provided
|
||||||
* context `evaluationContext` and gives back a result of type
|
* context `evaluationContext` and gives back a result of type
|
||||||
* `desiredType`.
|
* `desiredType`.
|
||||||
* @param <T> The type of the result desired.
|
* @param <T> The type of the result desired.
|
||||||
* @param expressionString The SpEL expression to evaluate.
|
* @param expressionString The SpEL expression to evaluate.
|
||||||
* @param evaluationContext The context in which the expression is to be evaluated.
|
* @param evaluationContext The context in which the expression is to be evaluated.
|
||||||
* @param desiredType The class of the result desired.
|
* @param desiredType The class of the result desired.
|
||||||
* @return The result of the evaluation of the expression.
|
* @return The result of the evaluation of the expression.
|
||||||
* @see ExpressionParser#parseExpression(String)
|
* @see ExpressionParser#parseExpression(String)
|
||||||
* @see Expression#getValue(EvaluationContext, Class)
|
* @see Expression#getValue(EvaluationContext, Class)
|
||||||
*/
|
*/
|
||||||
public <T> T evalExpression(final String expressionString,
|
public <T> T evalExpression(final String expressionString,
|
||||||
final EvaluationContext evaluationContext, final Class<T> desiredType) {
|
final EvaluationContext evaluationContext, final Class<T> desiredType) {
|
||||||
return PARSER.parseExpression(expressionString)
|
return PARSER.parseExpression(expressionString)
|
||||||
.getValue(evaluationContext, desiredType);
|
.getValue(evaluationContext, desiredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates multiple SpEL expressions and returns the result of the last
|
* Evaluates multiple SpEL expressions and returns the result of the last
|
||||||
* expression.
|
* expression.
|
||||||
* @param <T> The type of the result desired.
|
* @param <T> The type of the result desired.
|
||||||
* @param expressionStrings The SpEL expressions to evaluate.
|
* @param expressionStrings The SpEL expressions to evaluate.
|
||||||
* @param rootElement The root element in context of which the expressions
|
* @param rootElement The root element in context of which the expressions
|
||||||
* are to be evaluated.
|
* are to be evaluated.
|
||||||
* @param desiredType The class of the result desired.
|
* @param desiredType The class of the result desired.
|
||||||
* @return The result of the evaluation of the last expression.
|
* @return The result of the evaluation of the last expression.
|
||||||
* @see SpelHelper#evalExpression(String, EvaluationContext, Class)
|
* @see SpelHelper#evalExpression(String, EvaluationContext, Class)
|
||||||
* @see SpelHelper#evalExpression(String, Object, Class)
|
* @see SpelHelper#evalExpression(String, Object, Class)
|
||||||
*/
|
*/
|
||||||
public <T> T evalExpressions(final String[] expressionStrings,
|
public <T> T evalExpressions(final String[] expressionStrings,
|
||||||
final Object rootElement, final Class<T> desiredType) {
|
final Object rootElement, final Class<T> desiredType) {
|
||||||
return evalExpressions(
|
return evalExpressions(
|
||||||
expressionStrings, getEvaluationContext(rootElement), desiredType);
|
expressionStrings, getEvaluationContext(rootElement), desiredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates multiple SpEL expressions and returns the result of the last
|
* Evaluates multiple SpEL expressions and returns the result of the last
|
||||||
* expression.
|
* expression.
|
||||||
* @param <T> The type of the result desired.
|
* @param <T> The type of the result desired.
|
||||||
* @param expressionStrings The SpEL expressions to evaluate.
|
* @param expressionStrings The SpEL expressions to evaluate.
|
||||||
* @param evaluationContext The context in which the expression is to be evaluated.
|
* @param evaluationContext The context in which the expression is to be evaluated.
|
||||||
* @param desiredType The class of the result desired.
|
* @param desiredType The class of the result desired.
|
||||||
* @return The result of the evaluation of the last expression.
|
* @return The result of the evaluation of the last expression.
|
||||||
* @see SpelHelper#evalExpression(String, EvaluationContext, Class)
|
* @see SpelHelper#evalExpression(String, EvaluationContext, Class)
|
||||||
* @see SpelHelper#evalExpression(String, Object, Class)
|
* @see SpelHelper#evalExpression(String, Object, Class)
|
||||||
*/
|
*/
|
||||||
public <T> T evalExpressions(final String[] expressionStrings,
|
public <T> T evalExpressions(final String[] expressionStrings,
|
||||||
final EvaluationContext evaluationContext, final Class<T> desiredType) {
|
final EvaluationContext evaluationContext, final Class<T> desiredType) {
|
||||||
int length = expressionStrings.length;
|
int length = expressionStrings.length;
|
||||||
Assert.isTrue(length > 0,
|
Assert.isTrue(length > 0,
|
||||||
"expressionStrings should have length more than 0");
|
"expressionStrings should have length more than 0");
|
||||||
for (int i = 0; i < length - 1; i++) {
|
for (int i = 0; i < length - 1; i++) {
|
||||||
evalExpression(expressionStrings[i], evaluationContext, Object.class);
|
evalExpression(expressionStrings[i], evaluationContext, Object.class);
|
||||||
}
|
}
|
||||||
return evalExpression(expressionStrings[length - 1],
|
return evalExpression(expressionStrings[length - 1],
|
||||||
evaluationContext, desiredType);
|
evaluationContext, desiredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EvaluationContext getEvaluationContext(final Object rootObject) {
|
private EvaluationContext getEvaluationContext(final Object rootObject) {
|
||||||
StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject);
|
StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject);
|
||||||
newContext.getMethodResolvers().add(new ImplicitMethodResolver());
|
newContext.getMethodResolvers().add(new ImplicitMethodResolver());
|
||||||
newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor());
|
newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor());
|
||||||
newContext.setConstructorResolvers(
|
newContext.setConstructorResolvers(
|
||||||
asList((ConstructorResolver) new ImplicitConstructorResolver()));
|
asList((ConstructorResolver) new ImplicitConstructorResolver()));
|
||||||
for (Method method : registeredFunctions) {
|
for (Method method : registeredFunctions) {
|
||||||
newContext.setVariable(method.getName(), method);
|
newContext.setVariable(method.getName(), method);
|
||||||
}
|
}
|
||||||
newContext.setVariable(CONTEXT_LOOKUP_KEY, this);
|
newContext.setVariable(CONTEXT_LOOKUP_KEY, this);
|
||||||
return newContext;
|
return newContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up an implicit method registered with this instance.
|
* Looks up an implicit method registered with this instance.
|
||||||
* @param lookup key to lookup which should be of form:
|
* @param lookup key to lookup which should be of form:
|
||||||
* `method.getParameterTypes()[0].getName() + "." + method.getName()`
|
* `method.getParameterTypes()[0].getName() + "." + method.getName()`
|
||||||
* @return The registered method if found, else null.
|
* @return The registered method if found, else null.
|
||||||
*/
|
*/
|
||||||
public Method lookupImplicitMethod(final String lookup) {
|
public Method lookupImplicitMethod(final String lookup) {
|
||||||
Assert.notNull(lookup);
|
Assert.notNull(lookup);
|
||||||
return registeredMethods.get(lookup);
|
return registeredMethods.get(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up an implicit constructor registered with this instance.
|
* Looks up an implicit constructor registered with this instance.
|
||||||
* @param lookup key to lookup which should be of form:
|
* @param lookup key to lookup which should be of form:
|
||||||
* `constructor.getDeclaringClass().getSimpleName()`
|
* `constructor.getDeclaringClass().getSimpleName()`
|
||||||
* `+ Arrays.toString(constructor.getParameterTypes())`
|
* `+ Arrays.toString(constructor.getParameterTypes())`
|
||||||
* @return The registered constructor if found, else null.
|
* @return The registered constructor if found, else null.
|
||||||
*/
|
*/
|
||||||
public Constructor<?> lookupImplicitConstructor(final String lookup) {
|
public Constructor<?> lookupImplicitConstructor(final String lookup) {
|
||||||
Assert.notNull(lookup);
|
Assert.notNull(lookup);
|
||||||
return registeredConstructors.get(lookup);
|
return registeredConstructors.get(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current evaluation context. Null if there is no context.
|
* Returns the current evaluation context. Null if there is no context.
|
||||||
* @return The current evaluation context.
|
* @return The current evaluation context.
|
||||||
*/
|
*/
|
||||||
public static EvaluationContext getCurrentContext() {
|
public static EvaluationContext getCurrentContext() {
|
||||||
return CURRENT_CONTEXT.get();
|
return CURRENT_CONTEXT.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Method> filterMethods(final Class<?> clazz) {
|
private static List<Method> filterMethods(final Class<?> clazz) {
|
||||||
List<Method> allowedMethods = new ArrayList<Method>();
|
List<Method> allowedMethods = new ArrayList<Method>();
|
||||||
for (Method method : clazz.getMethods()) {
|
for (Method method : clazz.getMethods()) {
|
||||||
int modifiers = method.getModifiers();
|
int modifiers = method.getModifiers();
|
||||||
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
||||||
&& !method.getReturnType().equals(Void.TYPE)
|
&& !method.getReturnType().equals(Void.TYPE)
|
||||||
&& method.getParameterTypes().length > 0) {
|
&& method.getParameterTypes().length > 0) {
|
||||||
allowedMethods.add(method);
|
allowedMethods.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allowedMethods;
|
return allowedMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Method> filterFunctions(final Class<?> clazz) {
|
private static List<Method> filterFunctions(final Class<?> clazz) {
|
||||||
List<Method> allowedMethods = new ArrayList<Method>();
|
List<Method> allowedMethods = new ArrayList<Method>();
|
||||||
for (Method method : clazz.getMethods()) {
|
for (Method method : clazz.getMethods()) {
|
||||||
int modifiers = method.getModifiers();
|
int modifiers = method.getModifiers();
|
||||||
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
||||||
&& !method.getReturnType().equals(Void.TYPE)) {
|
&& !method.getReturnType().equals(Void.TYPE)) {
|
||||||
allowedMethods.add(method);
|
allowedMethods.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allowedMethods;
|
return allowedMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
package net.abhinavsarkar.spelhelper;
|
package net.abhinavsarkar.spelhelper;
|
||||||
|
|
||||||
public final class Functions {
|
public final class Functions {
|
||||||
|
|
||||||
public static String test(final String str) {
|
public static String test(final String str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String testNonPublic(final String str) {
|
static String testNonPublic(final String str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String testNonStatic(final String str) {
|
public String testNonStatic(final String str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void testVoid(final String str) {
|
public static void testVoid(final String str) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String testNoArg() {
|
public static String testNoArg() {
|
||||||
return "a";
|
return "a";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String testContext(final String str) {
|
public static String testContext(final String str) {
|
||||||
if (SpelHelper.getCurrentContext() == null) {
|
if (SpelHelper.getCurrentContext() == null) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
return o instanceof Functions;
|
return o instanceof Functions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
package net.abhinavsarkar.spelhelper
|
package net.abhinavsarkar.spelhelper
|
||||||
|
|
||||||
import org.scalatest.junit.JUnitRunner
|
import org.scalatest.junit.JUnitRunner
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.scalatest.FlatSpec
|
import org.scalatest.FlatSpec
|
||||||
import org.scalatest.junit.ShouldMatchersForJUnit
|
import org.scalatest.junit.ShouldMatchersForJUnit
|
||||||
import java.util.{Set => JSet, HashSet,
|
import java.util.{Set => JSet, HashSet,
|
||||||
List => JList, ArrayList,
|
List => JList, ArrayList,
|
||||||
Map => JMap, HashMap}
|
Map => JMap, HashMap}
|
||||||
import org.springframework.expression.spel.SpelEvaluationException
|
import org.springframework.expression.spel.SpelEvaluationException
|
||||||
|
|
||||||
@RunWith(classOf[JUnitRunner])
|
@RunWith(classOf[JUnitRunner])
|
||||||
class ExtensionFunctionsSpec extends FlatSpec with ShouldMatchersForJUnit {
|
class ExtensionFunctionsSpec extends FlatSpec with ShouldMatchersForJUnit {
|
||||||
|
|
||||||
"Extension Function 'list'" should "return a java.util.List " in {
|
"Extension Function 'list'" should "return a java.util.List " in {
|
||||||
val list: JList[String] = new ArrayList
|
val list: JList[String] = new ArrayList
|
||||||
List("a", "b", "c") foreach { list add _ }
|
List("a", "b", "c") foreach { list add _ }
|
||||||
new SpelHelper().evalExpression("#list('a','b','c')",
|
new SpelHelper().evalExpression("#list('a','b','c')",
|
||||||
new {}, classOf[JList[String]]) should equal(list)
|
new {}, classOf[JList[String]]) should equal(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Extension Function 'set'" should "return a java.util.Set " in {
|
"Extension Function 'set'" should "return a java.util.Set " in {
|
||||||
val set: JSet[String] = new HashSet
|
val set: JSet[String] = new HashSet
|
||||||
List("a", "b", "c") foreach { set add _ }
|
List("a", "b", "c") foreach { set add _ }
|
||||||
new SpelHelper().evalExpression("#set('a','b','c')",
|
new SpelHelper().evalExpression("#set('a','b','c')",
|
||||||
new {}, classOf[JSet[String]]) should equal(set)
|
new {}, classOf[JSet[String]]) should equal(set)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Extension Function 'map'" should "return a java.util.Map " in {
|
"Extension Function 'map'" should "return a java.util.Map " in {
|
||||||
val map: JMap[String,Int] = new HashMap
|
val map: JMap[String,Int] = new HashMap
|
||||||
List("a", "b", "c").zipWithIndex.foreach { x => map.put(x._1, x._2) }
|
List("a", "b", "c").zipWithIndex.foreach { x => map.put(x._1, x._2) }
|
||||||
new SpelHelper().evalExpression("#map(#list('a','b','c'),#list(0,1,2))",
|
new SpelHelper().evalExpression("#map(#list('a','b','c'),#list(0,1,2))",
|
||||||
new {}, classOf[JMap[String,Int]]) should equal(map)
|
new {}, classOf[JMap[String,Int]]) should equal(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Extension Function 'map'" should "throw SpelEvaluationException " +
|
"Extension Function 'map'" should "throw SpelEvaluationException " +
|
||||||
"if length of key and values lists is not same " in {
|
"if length of key and values lists is not same " in {
|
||||||
evaluating { new SpelHelper().evalExpression("#map(#list('a','b','c'),#list(1,2))",
|
evaluating { new SpelHelper().evalExpression("#map(#list('a','b','c'),#list(1,2))",
|
||||||
new {}, classOf[JMap[String,Int]]) } should produce [SpelEvaluationException]
|
new {}, classOf[JMap[String,Int]]) } should produce [SpelEvaluationException]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
package net.abhinavsarkar.spelhelper
|
package net.abhinavsarkar.spelhelper
|
||||||
|
|
||||||
import org.scalatest.junit.JUnitRunner
|
import org.scalatest.junit.JUnitRunner
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.scalatest.FlatSpec
|
import org.scalatest.FlatSpec
|
||||||
import org.scalatest.junit.ShouldMatchersForJUnit
|
import org.scalatest.junit.ShouldMatchersForJUnit
|
||||||
import java.util.{HashSet, Set => JSet, List => JList, ArrayList}
|
import java.util.{HashSet, Set => JSet, List => JList, ArrayList}
|
||||||
|
|
||||||
@RunWith(classOf[JUnitRunner])
|
@RunWith(classOf[JUnitRunner])
|
||||||
class ImplicitMethodsSpec extends FlatSpec with ShouldMatchersForJUnit {
|
class ImplicitMethodsSpec extends FlatSpec with ShouldMatchersForJUnit {
|
||||||
|
|
||||||
"Implicit Function 'distinct' on List" should
|
"Implicit Function 'distinct' on List" should
|
||||||
"return distinct items in a list " in {
|
"return distinct items in a list " in {
|
||||||
val set: JSet[String] = new HashSet
|
val set: JSet[String] = new HashSet
|
||||||
set add "a"; set add "b"
|
set add "a"; set add "b"
|
||||||
new SpelHelper().evalExpression("#list('a','b','a').distinct()",
|
new SpelHelper().evalExpression("#list('a','b','a').distinct()",
|
||||||
new {}, classOf[JSet[String]]) should equal(set)
|
new {}, classOf[JSet[String]]) should equal(set)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Implicit Function 'sorted' on List" should
|
"Implicit Function 'sorted' on List" should
|
||||||
"return a sorted list " in {
|
"return a sorted list " in {
|
||||||
val list: JList[String] = new ArrayList
|
val list: JList[String] = new ArrayList
|
||||||
List("a", "b", "c") foreach { list add _ }
|
List("a", "b", "c") foreach { list add _ }
|
||||||
new SpelHelper().evalExpression("#list('c','b','a').sorted()",
|
new SpelHelper().evalExpression("#list('c','b','a').sorted()",
|
||||||
new {}, classOf[JList[String]]) should equal(list)
|
new {}, classOf[JList[String]]) should equal(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Implicit Function 'reversed' on List" should
|
"Implicit Function 'reversed' on List" should
|
||||||
"return a reversed list " in {
|
"return a reversed list " in {
|
||||||
val list: JList[String] = new ArrayList
|
val list: JList[String] = new ArrayList
|
||||||
List("a", "b", "c") foreach { list add _ }
|
List("a", "b", "c") foreach { list add _ }
|
||||||
new SpelHelper().evalExpression("#list('c','b','a').reversed()",
|
new SpelHelper().evalExpression("#list('c','b','a').reversed()",
|
||||||
new {}, classOf[JList[String]]) should equal(list)
|
new {}, classOf[JList[String]]) should equal(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Implicit Function 'take' on List" should
|
"Implicit Function 'take' on List" should
|
||||||
"return a list containing first n items of a list " in {
|
"return a list containing first n items of a list " in {
|
||||||
val list: JList[String] = new ArrayList
|
val list: JList[String] = new ArrayList
|
||||||
List("a", "b", "c") foreach { list add _ }
|
List("a", "b", "c") foreach { list add _ }
|
||||||
new SpelHelper().evalExpression("#list('a','b','c','d').take(3)",
|
new SpelHelper().evalExpression("#list('a','b','c','d').take(3)",
|
||||||
new {}, classOf[JList[String]]) should equal(list)
|
new {}, classOf[JList[String]]) should equal(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
"Implicit Function 'drop' on List" should
|
"Implicit Function 'drop' on List" should
|
||||||
"return a list containing items after the first n items of a list " in {
|
"return a list containing items after the first n items of a list " in {
|
||||||
val list: JList[String] = new ArrayList
|
val list: JList[String] = new ArrayList
|
||||||
List("c", "d") foreach { list add _ }
|
List("c", "d") foreach { list add _ }
|
||||||
new SpelHelper().evalExpression("#list('a','b','c','d').drop(2)",
|
new SpelHelper().evalExpression("#list('a','b','c','d').drop(2)",
|
||||||
new {}, classOf[JList[String]]) should equal(list)
|
new {}, classOf[JList[String]]) should equal(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,103 +1,103 @@
|
||||||
package net.abhinavsarkar.spelhelper
|
package net.abhinavsarkar.spelhelper
|
||||||
|
|
||||||
import org.scalatest.junit.JUnitRunner
|
import org.scalatest.junit.JUnitRunner
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.scalatest.FlatSpec
|
import org.scalatest.FlatSpec
|
||||||
import org.scalatest.junit.ShouldMatchersForJUnit
|
import org.scalatest.junit.ShouldMatchersForJUnit
|
||||||
import org.springframework.expression.spel.SpelEvaluationException
|
import org.springframework.expression.spel.SpelEvaluationException
|
||||||
|
|
||||||
@RunWith(classOf[JUnitRunner])
|
@RunWith(classOf[JUnitRunner])
|
||||||
class SpelHelperSpec extends FlatSpec with ShouldMatchersForJUnit {
|
class SpelHelperSpec extends FlatSpec with ShouldMatchersForJUnit {
|
||||||
|
|
||||||
"SpelHelper" should "register and evaluate functions " in {
|
"SpelHelper" should "register and evaluate functions " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerFunctionsFromClass(classOf[Functions])
|
.registerFunctionsFromClass(classOf[Functions])
|
||||||
.evalExpression(
|
.evalExpression(
|
||||||
"#test('check')", new {}, classOf[String]) should equal ("check")
|
"#test('check')", new {}, classOf[String]) should equal ("check")
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "not register non public methods " in {
|
it should "not register non public methods " in {
|
||||||
val spelHelper = new SpelHelper()
|
val spelHelper = new SpelHelper()
|
||||||
.registerFunctionsFromClass(classOf[Functions])
|
.registerFunctionsFromClass(classOf[Functions])
|
||||||
evaluating { spelHelper.evalExpression("#testNonPublic('check')",
|
evaluating { spelHelper.evalExpression("#testNonPublic('check')",
|
||||||
new {}, classOf[String]) } should produce [SpelEvaluationException]
|
new {}, classOf[String]) } should produce [SpelEvaluationException]
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "not register non static methods " in {
|
it should "not register non static methods " in {
|
||||||
val spelHelper = new SpelHelper()
|
val spelHelper = new SpelHelper()
|
||||||
.registerFunctionsFromClass(classOf[Functions])
|
.registerFunctionsFromClass(classOf[Functions])
|
||||||
evaluating { spelHelper.evalExpression("#testNonStatic('check')",
|
evaluating { spelHelper.evalExpression("#testNonStatic('check')",
|
||||||
new {}, classOf[String]) } should produce [SpelEvaluationException]
|
new {}, classOf[String]) } should produce [SpelEvaluationException]
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "not register void methods " in {
|
it should "not register void methods " in {
|
||||||
val spelHelper = new SpelHelper()
|
val spelHelper = new SpelHelper()
|
||||||
.registerFunctionsFromClass(classOf[Functions])
|
.registerFunctionsFromClass(classOf[Functions])
|
||||||
evaluating { spelHelper.evalExpression("#testVoid('check')",
|
evaluating { spelHelper.evalExpression("#testVoid('check')",
|
||||||
new {}, classOf[String]) } should produce [SpelEvaluationException]
|
new {}, classOf[String]) } should produce [SpelEvaluationException]
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "register implicit methods " in {
|
it should "register implicit methods " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerImplicitMethodsFromClass(classOf[Functions])
|
.registerImplicitMethodsFromClass(classOf[Functions])
|
||||||
.lookupImplicitMethod("java.lang.String.test") should equal(
|
.lookupImplicitMethod("java.lang.String.test") should equal(
|
||||||
classOf[Functions].getMethod("test", classOf[String]))
|
classOf[Functions].getMethod("test", classOf[String]))
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "not register methods with no args as implicit methods " in {
|
it should "not register methods with no args as implicit methods " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerImplicitMethodsFromClass(classOf[Functions])
|
.registerImplicitMethodsFromClass(classOf[Functions])
|
||||||
.lookupImplicitMethod("java.lang.String.testNoArg") should be (null);
|
.lookupImplicitMethod("java.lang.String.testNoArg") should be (null);
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "register implicit constructors " in {
|
it should "register implicit constructors " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerConstructorsFromClass(classOf[Functions])
|
.registerConstructorsFromClass(classOf[Functions])
|
||||||
.lookupImplicitConstructor("Functions[]") should equal(
|
.lookupImplicitConstructor("Functions[]") should equal(
|
||||||
classOf[Functions].getConstructor())
|
classOf[Functions].getConstructor())
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "evaluate implicit methods " in {
|
it should "evaluate implicit methods " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerImplicitMethodsFromClass(classOf[Functions])
|
.registerImplicitMethodsFromClass(classOf[Functions])
|
||||||
.evalExpression(
|
.evalExpression(
|
||||||
"'check'.test()", new {}, classOf[String]) should equal ("check")
|
"'check'.test()", new {}, classOf[String]) should equal ("check")
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "evaluate implicit constructors " in {
|
it should "evaluate implicit constructors " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerConstructorsFromClass(classOf[Functions])
|
.registerConstructorsFromClass(classOf[Functions])
|
||||||
.evalExpression(
|
.evalExpression(
|
||||||
"new Functions()", new {}, classOf[Functions]) should equal (new Functions)
|
"new Functions()", new {}, classOf[Functions]) should equal (new Functions)
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "evaluate implicit properties " in {
|
it should "evaluate implicit properties " in {
|
||||||
new SpelHelper().evalExpression(
|
new SpelHelper().evalExpression(
|
||||||
"'abc'.hashCode", new {}, classOf[int]) should equal ("abc".hashCode)
|
"'abc'.hashCode", new {}, classOf[int]) should equal ("abc".hashCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "evaluate multiple expressions " in {
|
it should "evaluate multiple expressions " in {
|
||||||
new SpelHelper().evalExpressions(
|
new SpelHelper().evalExpressions(
|
||||||
Array("#s='check'", "#s"), new {}, classOf[String]) should equal ("check")
|
Array("#s='check'", "#s"), new {}, classOf[String]) should equal ("check")
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "throw IllegalArgumentException when trying to evaluate " +
|
it should "throw IllegalArgumentException when trying to evaluate " +
|
||||||
"blank multiple expressions " in {
|
"blank multiple expressions " in {
|
||||||
evaluating { new SpelHelper().evalExpressions(
|
evaluating { new SpelHelper().evalExpressions(
|
||||||
Array[String](), new {}, classOf[String]) } should produce [IllegalArgumentException]
|
Array[String](), new {}, classOf[String]) } should produce [IllegalArgumentException]
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "return evaluation context inside a method called " +
|
it should "return evaluation context inside a method called " +
|
||||||
"from SpEL expression " in {
|
"from SpEL expression " in {
|
||||||
new SpelHelper()
|
new SpelHelper()
|
||||||
.registerFunctionsFromClass(classOf[Functions])
|
.registerFunctionsFromClass(classOf[Functions])
|
||||||
.evalExpression(
|
.evalExpression(
|
||||||
"#testContext('check')", new {}, classOf[String]) should equal ("check")
|
"#testContext('check')", new {}, classOf[String]) should equal ("check")
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "not return evaluation context outside a method called " +
|
it should "not return evaluation context outside a method called " +
|
||||||
"from SpEL expression " in {
|
"from SpEL expression " in {
|
||||||
SpelHelper.getCurrentContext should be (null)
|
SpelHelper.getCurrentContext should be (null)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue