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