parent
f39f6ff692
commit
9fe01a9403
@ -1,2 +1,4 @@ |
||||
target/* |
||||
.pmd |
||||
target/* |
||||
.pmd |
||||
.scala_dependencies |
||||
.settings/ |
||||
|
@ -1,97 +1,97 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 <T> Type of the arguments provided. |
||||
* @param args Arguments to create list of. |
||||
* @return An unmodifiable list of the arguments provided. |
||||
*/ |
||||
public static <T> List<T> 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 <T> Type of the arguments provided. |
||||
* @param args Arguments to create set of. |
||||
* @return An unmodifiable set of the arguments provided. |
||||
*/ |
||||
public static <T> Set<T> set(final T... args) { |
||||
return unmodifiableSet(new HashSet<T>(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 <K> Type of the keys of the map. |
||||
* @param <V> 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 <K,V> Map<K,V> 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<K,V> map = new HashMap<K,V>(); |
||||
int length = keys.size(); |
||||
for (int i = 0; i < length; i++) { |
||||
map.put(keys.get(i), values.get(i)); |
||||
} |
||||
return unmodifiableMap(map); |
||||
} |
||||
|
||||
} |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 <T> Type of the arguments provided. |
||||
* @param args Arguments to create list of. |
||||
* @return An unmodifiable list of the arguments provided. |
||||
*/ |
||||
public static <T> List<T> 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 <T> Type of the arguments provided. |
||||
* @param args Arguments to create set of. |
||||
* @return An unmodifiable set of the arguments provided. |
||||
*/ |
||||
public static <T> Set<T> set(final T... args) { |
||||
return unmodifiableSet(new HashSet<T>(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 <K> Type of the keys of the map. |
||||
* @param <V> 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 <K,V> Map<K,V> 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<K,V> map = new HashMap<K,V>(); |
||||
int length = keys.size(); |
||||
for (int i = 0; i < length; i++) { |
||||
map.put(keys.get(i), values.get(i)); |
||||
} |
||||
return unmodifiableMap(map); |
||||
} |
||||
|
||||
} |
||||
|
@ -1,48 +1,52 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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<TypeDescriptor> 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; |
||||
} |
||||
} |
||||
} |
@ -1,113 +1,120 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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<String, MethodExecutor> CACHE = |
||||
new ConcurrentHashMap<String, MethodExecutor>(); |
||||
|
||||
private static final MethodExecutor NULL_ME = new MethodExecutor() { |
||||
public TypedValue execute(final EvaluationContext context, final Object target, |
||||
final Object... arguments) throws AccessException { |
||||
return null; |
||||
} |
||||
}; |
||||
|
||||
private static final class ImplicitMethodExecutor implements |
||||
MethodExecutor { |
||||
private final MethodExecutor executor; |
||||
|
||||
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 <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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<String, MethodExecutor> CACHE = |
||||
new ConcurrentHashMap<String, MethodExecutor>(); |
||||
|
||||
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<TypeDescriptor> 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<TypeDescriptor> newArgumentTypes = new ArrayList<TypeDescriptor>(); |
||||
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; |
||||
} |
||||
|
||||
} |
@ -1,129 +1,129 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 <T> 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 <T> Set<T> distinct(final List<? extends T> list) { |
||||
return unmodifiableSet(new HashSet<T>(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 <T> 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 <T extends Comparable<? super T>> List<T> sorted( |
||||
final List<? extends T> list) { |
||||
List<T> temp = new ArrayList<T>(list); |
||||
Collections.sort(temp); |
||||
return unmodifiableList(temp); |
||||
} |
||||
|
||||
/** |
||||
* 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 <T> 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 <T> List<T> reversed(final List<? extends T> list) { |
||||
List<T> temp = new ArrayList<T>(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 <T> 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 <T> List<T> take(final List<T> 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 <T> 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 <T> List<T> drop(final List<T> list, final int n) { |
||||
return unmodifiableList(list.subList(n, list.size())); |
||||
} |
||||
|
||||
} |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 <T> 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 <T> Set<T> distinct(final List<? extends T> list) { |
||||
return unmodifiableSet(new HashSet<T>(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 <T> 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 <T extends Comparable<? super T>> List<T> sorted( |
||||
final List<? extends T> list) { |
||||
List<T> temp = new ArrayList<T>(list); |
||||
Collections.sort(temp); |
||||
return unmodifiableList(temp); |
||||
} |
||||
|
||||
/** |
||||
* 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 <T> 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 <T> List<T> reversed(final List<? extends T> list) { |
||||
List<T> temp = new ArrayList<T>(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 <T> 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 <T> List<T> take(final List<T> 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 <T> 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 <T> List<T> drop(final List<T> list, final int n) { |
||||
return unmodifiableList(list.subList(n, list.size())); |
||||
} |
||||
|
||||
} |
||||
|
@ -1,67 +1,70 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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<String, MethodExecutor> CACHE = |
||||
new ConcurrentHashMap<String, MethodExecutor>(); |
||||
|
||||
public boolean canRead(final EvaluationContext context, |
||||
final Object target, final String name) |
||||
throws AccessException { |
||||
Assert.notNull(target, "target is null"); |
||||
String cacheKey = target.getClass().getName() + "." + name; |
||||
if (CACHE.containsKey(cacheKey)) { |
||||
return CACHE.get(cacheKey) != null; |
||||
} |
||||
|
||||
for (MethodResolver mr : context.getMethodResolvers()) { |
||||
MethodExecutor me = mr.resolve(context, target, name, new Class[0]); |
||||
if (me != null) { |
||||
CACHE.putIfAbsent(cacheKey, me); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
CACHE.putIfAbsent(cacheKey, null); |
||||
return false; |
||||
} |
||||
|
||||
public TypedValue read(final EvaluationContext context, |
||||
final Object target, final String name) |
||||
throws AccessException { |
||||
if (canRead(context, target, name)) { |
||||
String cacheKey = target.getClass().getName() + "." + name; |
||||
return CACHE.get(cacheKey).execute(context, target, new Object[0]); |
||||
} |
||||
throw new AccessException(MessageFormat.format( |
||||
"Cannot read property: {0} of target: {1}", name, target)); |
||||
} |
||||
|
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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<String, MethodExecutor> CACHE = |
||||
new ConcurrentHashMap<String, MethodExecutor>(); |
||||
|
||||
public boolean canRead(final EvaluationContext context, |
||||
final Object target, final String name) |
||||
throws AccessException { |
||||
Assert.notNull(target, "target is null"); |
||||
String cacheKey = target.getClass().getName() + "." + name; |
||||
if (CACHE.containsKey(cacheKey)) { |
||||
return CACHE.get(cacheKey) != null; |
||||
} |
||||
|
||||
for (MethodResolver mr : context.getMethodResolvers()) { |
||||
MethodExecutor me = |
||||
mr.resolve(context, target, name, Collections.<TypeDescriptor>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)); |
||||
} |
||||
|
||||
} |
@ -1,86 +1,86 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package net.abhinavsarkar.spelhelper; |
||||
|
||||
import java.util.LinkedHashSet; |
||||
import java.util.Set; |
||||
|
||||
final class InheritenceUtil { |
||||
|
||||
private InheritenceUtil() { |
||||
} |
||||
|
||||
public static Set<Class<?>> getInheritance(final Class<?> clazz) { |
||||
LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>(); |
||||
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<Class<?>> 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<Class<?>> 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 <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package net.abhinavsarkar.spelhelper; |
||||
|
||||
import java.util.LinkedHashSet; |
||||
import java.util.Set; |
||||
|
||||
final class InheritenceUtil { |
||||
|
||||
private InheritenceUtil() { |
||||
} |
||||
|
||||
public static Set<Class<?>> getInheritance(final Class<?> clazz) { |
||||
LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>(); |
||||
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<Class<?>> 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<Class<?>> 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(); |
||||
} |
||||
|
||||
} |
||||
|
@ -1,45 +1,45 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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)); |
||||
} |
||||
|
||||
} |
@ -1,349 +1,349 @@ |
||||
/* Copyright 2010 Abhinav Sarkar <abhinav@abhinavsarkar.net> |
||||
* |
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
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 |
||||