diff --git a/src/main/java/net/abhinavsarkar/spelhelper/ExtensionFunctions.java b/src/main/java/net/abhinavsarkar/spelhelper/ExtensionFunctions.java index 42ed46b..bc4871f 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ExtensionFunctions.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ExtensionFunctions.java @@ -24,7 +24,7 @@ final class ExtensionFunctions { } public static Map map(final List keys, - final List values) { + final List values) { Assert.isTrue(keys.size() == values.size(), "There should equal number of keys and values"); Map map = new HashMap(); diff --git a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitConstructorResolver.java b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitConstructorResolver.java index 44ee05e..0f24173 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitConstructorResolver.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitConstructorResolver.java @@ -17,18 +17,18 @@ final class ImplicitConstructorResolver implements private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver(); - public ConstructorExecutor resolve(final EvaluationContext context, + 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; - } + 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; + } } } \ 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 2ebf026..b4506de 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java @@ -16,83 +16,83 @@ import org.springframework.expression.spel.support.ReflectiveMethodResolver; public final class ImplicitMethodResolver implements MethodResolver { - private static final ConcurrentHashMap cache = - new ConcurrentHashMap(); + 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 MethodExecutor NULL_ME = new MethodExecutor() { + public TypedValue execute(final EvaluationContext context, final Object target, + final Object... arguments) throws AccessException { + return null; + } + }; - private static final class ImplicitMethodExecutor implements - MethodExecutor { - private final MethodExecutor executor; + private static final class ImplicitMethodExecutor implements + MethodExecutor { + private final MethodExecutor executor; - private ImplicitMethodExecutor(final MethodExecutor executor) { - this.executor = executor; - } + private ImplicitMethodExecutor(final MethodExecutor executor) { + this.executor = executor; + } - public TypedValue execute(final EvaluationContext context, final Object target, - final Object... arguments) throws AccessException { - Object[] modifiedArguments = new Object[arguments.length + 1]; - modifiedArguments[0] = target; - System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length); - return executor.execute(context, null, modifiedArguments); - } - } + public 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; - } + public MethodExecutor resolve(final EvaluationContext context, + final Object targetObject, final String name, final Class[] argumentTypes) + throws AccessException { + if (targetObject == null) { + return null; + } + Class type = targetObject.getClass(); + String cacheKey = type.getName() + "." + name; + if (cache.containsKey(cacheKey)) { + MethodExecutor executor = cache.get(cacheKey); + return executor == NULL_ME ? null : executor; + } - Method method = lookupMethod(context, type, name); - if (method != null) { - int modifiers = method.getModifiers(); - if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) { - Class[] parameterTypes = method.getParameterTypes(); - Class firstParameterType = parameterTypes[0]; - if (parameterTypes.length > 0 - && firstParameterType.isAssignableFrom(type)) { + Method method = lookupMethod(context, type, name); + if (method != null) { + int modifiers = method.getModifiers(); + if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) { + Class[] parameterTypes = method.getParameterTypes(); + Class firstParameterType = parameterTypes[0]; + if (parameterTypes.length > 0 + && firstParameterType.isAssignableFrom(type)) { - Class[] modifiedArgumentTypes = new Class[argumentTypes.length + 1]; - modifiedArgumentTypes[0] = firstParameterType; - System.arraycopy(argumentTypes, 0, modifiedArgumentTypes, - 1, argumentTypes.length); - MethodExecutor executor = new ReflectiveMethodResolver() - .resolve(context, method.getDeclaringClass(), name, - modifiedArgumentTypes); - MethodExecutor wrappedExecutor = executor == null ? null - : new ImplicitMethodExecutor(executor); - cache.putIfAbsent(cacheKey, wrappedExecutor); - return wrappedExecutor; - } - } - } - cache.putIfAbsent(cacheKey, NULL_ME); - return null; - } + Class[] modifiedArgumentTypes = new Class[argumentTypes.length + 1]; + modifiedArgumentTypes[0] = firstParameterType; + System.arraycopy(argumentTypes, 0, modifiedArgumentTypes, + 1, argumentTypes.length); + MethodExecutor executor = new ReflectiveMethodResolver() + .resolve(context, method.getDeclaringClass(), name, + modifiedArgumentTypes); + MethodExecutor wrappedExecutor = executor == null ? null + : new ImplicitMethodExecutor(executor); + cache.putIfAbsent(cacheKey, wrappedExecutor); + return wrappedExecutor; + } + } + } + cache.putIfAbsent(cacheKey, NULL_ME); + return null; + } - private static Method lookupMethod(final EvaluationContext context, - final Class type, final String name) { - for (Class clazz : InheritenceUtil.getInheritance(type)) { - Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY)) - .lookupImplicitMethod(clazz.getName() + "." + name); - if (variable instanceof Method) { - return (Method) variable; - } - } - return null; - } + 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 9864bb1..4050a55 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java @@ -12,28 +12,28 @@ import java.util.Set; final class ImplicitMethods { public static Set distinct(final List list) { - return unmodifiableSet(new HashSet(list)); + return unmodifiableSet(new HashSet(list)); } public static > List sorted( - final List list) { - List temp = new ArrayList(list); - Collections.sort(temp); - return unmodifiableList(temp); + final List list) { + List temp = new ArrayList(list); + Collections.sort(temp); + return unmodifiableList(temp); } public static List reversed(final List list) { - List temp = new ArrayList(list); - Collections.reverse(temp); - return unmodifiableList(temp); + List temp = new ArrayList(list); + Collections.reverse(temp); + return unmodifiableList(temp); } public static List take(final List list, final int n) { - return unmodifiableList(list.subList(0, n)); + return unmodifiableList(list.subList(0, n)); } public static List drop(final List list, final int n) { - return unmodifiableList(list.subList(n, list.size())); + 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 8322ff4..9877490 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java @@ -14,40 +14,40 @@ import org.springframework.expression.TypedValue; import org.springframework.util.Assert; public 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; - } + + 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)); - } - + 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 c9267e4..4c82276 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java @@ -5,62 +5,62 @@ import java.util.Set; final class InheritenceUtil { - public static Set> getInheritance(final Class in) { - LinkedHashSet> result = new LinkedHashSet>(); - result.add(in); - getInheritance(in, result); - return result; - } + public static Set> getInheritance(final Class in) { + LinkedHashSet> result = new LinkedHashSet>(); + result.add(in); + getInheritance(in, result); + return result; + } - /** - * Get inheritance of type. - * - * @param in - * @param result - */ - private static void getInheritance(final Class in, final Set> result) { - Class superclass = getSuperclass(in); + /** + * Get inheritance of type. + * + * @param in + * @param result + */ + private static void getInheritance(final Class in, final Set> result) { + Class superclass = getSuperclass(in); - if (superclass != null) { - result.add(superclass); - getInheritance(superclass, result); - } + if (superclass != null) { + result.add(superclass); + getInheritance(superclass, result); + } - getInterfaceInheritance(in, result); - } + getInterfaceInheritance(in, result); + } - /** - * Get interfaces that the type inherits from. - * - * @param in - * @param result - */ - private static void getInterfaceInheritance(final Class in, - final Set> result) { - for (Class c : in.getInterfaces()) { - result.add(c); - getInterfaceInheritance(c, result); - } - } + /** + * Get interfaces that the type inherits from. + * + * @param in + * @param result + */ + private static void getInterfaceInheritance(final Class in, + final Set> result) { + for (Class c : in.getInterfaces()) { + result.add(c); + getInterfaceInheritance(c, result); + } + } - /** - * Get superclass of class. - * - * @param in - * @return - */ - private static Class getSuperclass(final Class in) { - if (in == null) { - return null; - } - if (in.isArray() && in != Object[].class) { - Class type = in.getComponentType(); - while (type.isArray()) { - type = type.getComponentType(); - } - return type; - } - return in.getSuperclass(); - } + /** + * Get superclass of class. + * + * @param in + * @return + */ + private static Class getSuperclass(final Class in) { + if (in == null) { + return null; + } + if (in.isArray() && in != Object[].class) { + Class type = in.getComponentType(); + while (type.isArray()) { + type = type.getComponentType(); + } + return type; + } + return in.getSuperclass(); + } } diff --git a/src/main/java/net/abhinavsarkar/spelhelper/ReadOnlyGenericPropertyAccessor.java b/src/main/java/net/abhinavsarkar/spelhelper/ReadOnlyGenericPropertyAccessor.java index c2aa4d9..a6ff27b 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ReadOnlyGenericPropertyAccessor.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ReadOnlyGenericPropertyAccessor.java @@ -7,22 +7,22 @@ import org.springframework.expression.EvaluationContext; import org.springframework.expression.PropertyAccessor; public abstract class ReadOnlyGenericPropertyAccessor implements - PropertyAccessor { + PropertyAccessor { - public final boolean canWrite(final EvaluationContext context, - final Object target, final String name) throws AccessException { - return false; - } + public final boolean canWrite(final EvaluationContext context, + final Object target, final String name) throws AccessException { + return false; + } - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") public final Class[] getSpecificTargetClasses() { - return null; - } + 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)); - } + 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 de6ca25..3e3496a 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java @@ -22,110 +22,110 @@ import org.springframework.util.Assert; public final class SpelHelper { - public static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName(); + public static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName(); - private static final ExpressionParser PARSER = new SpelExpressionParser(); - private static final ThreadLocal currentContext = - new ThreadLocal(); + private static final ExpressionParser PARSER = new SpelExpressionParser(); + private static final ThreadLocal currentContext = + new ThreadLocal(); - private volatile EvaluationContext context; - private final Set registeredFunctions = new HashSet(); - private final Map registeredMethods = - new ConcurrentHashMap(); + private volatile EvaluationContext context; + private final Set registeredFunctions = new HashSet(); + private final Map registeredMethods = + new ConcurrentHashMap(); private final Map> registeredConstructors = - new ConcurrentHashMap>(); + new ConcurrentHashMap>(); { registerFunctionsFromClass(ExtensionFunctions.class); registerImplicitMethodsFromClass(ImplicitMethods.class); } - public SpelHelper registerImplicitMethodsFromClass(final Class clazz) { - for (Method method : filterMethods(clazz)) { - registeredMethods.put(String.format( - "%s.%s", method.getParameterTypes()[0].getName(), method.getName()), - method); - } - return this; - } + public SpelHelper registerImplicitMethodsFromClass(final Class clazz) { + for (Method method : filterMethods(clazz)) { + registeredMethods.put(String.format( + "%s.%s", method.getParameterTypes()[0].getName(), method.getName()), + method); + } + return this; + } public SpelHelper registerFunctionsFromClass(final Class clazz) { registeredFunctions.addAll(filterMethods(clazz)); - context = null; - return this; - } + context = null; + return this; + } public SpelHelper registerImplicitConstructorsFromClass(final Class clazz) { - for (Constructor constructor : asList(clazz.getConstructors())) { - registeredConstructors.put( - constructor.getDeclaringClass().getSimpleName() + for (Constructor constructor : asList(clazz.getConstructors())) { + registeredConstructors.put( + constructor.getDeclaringClass().getSimpleName() + Arrays.toString(constructor.getParameterTypes()), constructor); - } + } return this; - } + } public T evalExpression(final String expressionString, - final Object rootElement, final Class desiredType) { - EvaluationContext evaluationContext = getEvaluationContext(rootElement); - currentContext.set(evaluationContext); - T value = evalExpression(expressionString, evaluationContext, desiredType); - currentContext.set(null); + final Object rootElement, final Class desiredType) { + EvaluationContext evaluationContext = getEvaluationContext(rootElement); + currentContext.set(evaluationContext); + T value = evalExpression(expressionString, evaluationContext, desiredType); + currentContext.set(null); - return value; - } + return value; + } - public T evalExpression(final String expressionString, + public T evalExpression(final String expressionString, final EvaluationContext evaluationContext, final Class desiredType) { - return PARSER.parseExpression(expressionString) - .getValue(evaluationContext, desiredType); + return PARSER.parseExpression(expressionString) + .getValue(evaluationContext, desiredType); } public T evalExpressions(final String[] expressionStrings, - final Object rootElement, final Class desiredType) { + final Object rootElement, 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], rootElement, Object.class); } - return evalExpression(expressionStrings[length - 1], + return evalExpression(expressionStrings[length - 1], rootElement, desiredType); - } + } - private EvaluationContext getEvaluationContext(final Object rootObject) { - if (context == null) { - synchronized (PARSER) { - if (context == null) { - StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject); - newContext.getMethodResolvers().add(new ImplicitMethodResolver()); - newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor()); - newContext.setConstructorResolvers( - asList((ConstructorResolver) new ImplicitConstructorResolver())); + private EvaluationContext getEvaluationContext(final Object rootObject) { + if (context == null) { + synchronized (PARSER) { + if (context == null) { + StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject); + newContext.getMethodResolvers().add(new ImplicitMethodResolver()); + newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor()); + newContext.setConstructorResolvers( + asList((ConstructorResolver) new ImplicitConstructorResolver())); for (Method method : registeredFunctions) { - newContext.setVariable(method.getName(), method); - } + newContext.setVariable(method.getName(), method); + } newContext.setVariable(CONTEXT_LOOKUP_KEY, this); context = newContext; - } - } - } - return context; - } - - public Method lookupImplicitMethod(final String lookup) { - Assert.notNull(lookup); - return registeredMethods.get(lookup); + } + } + } + return context; } - public Constructor lookupImplicitConstructor(final String lookup) { - Assert.notNull(lookup); - return registeredConstructors.get(lookup); + public Method lookupImplicitMethod(final String lookup) { + Assert.notNull(lookup); + return registeredMethods.get(lookup); } - public static EvaluationContext getCurrentContext() { - return currentContext.get(); - } + public Constructor lookupImplicitConstructor(final String lookup) { + Assert.notNull(lookup); + return registeredConstructors.get(lookup); + } + + public static EvaluationContext getCurrentContext() { + return currentContext.get(); + } private static List filterMethods(final Class clazz) { List allowedMethods = new ArrayList(); diff --git a/src/test/java/net/abhinavsarkar/spelhelper/SpelHelperTest.java b/src/test/java/net/abhinavsarkar/spelhelper/SpelHelperTest.java index b46d163..6539527 100644 --- a/src/test/java/net/abhinavsarkar/spelhelper/SpelHelperTest.java +++ b/src/test/java/net/abhinavsarkar/spelhelper/SpelHelperTest.java @@ -8,36 +8,36 @@ import org.junit.Test; public class SpelHelperTest { - @Test - public void testRegisteredFunction() { - Assert.assertEquals( - Arrays.asList("abhinav", "mini", "dan"), - new SpelHelper().evalExpression( - "#list('abhinav','mini','dan')", new Object(), List.class)); - } + @Test + public void testRegisteredFunction() { + Assert.assertEquals( + Arrays.asList("abhinav", "mini", "dan"), + new SpelHelper().evalExpression( + "#list('abhinav','mini','dan')", new Object(), List.class)); + } - @Test - public void testImplicitMethod() { - Assert.assertEquals( - Arrays.asList("abhinav", "dan", "mini"), - new SpelHelper().evalExpression( - "#list('abhinav','mini','dan').sorted", new Object(), List.class)); - } + @Test + public void testImplicitMethod() { + Assert.assertEquals( + Arrays.asList("abhinav", "dan", "mini"), + new SpelHelper().evalExpression( + "#list('abhinav','mini','dan').sorted", new Object(), List.class)); + } - public static final class ConstructorTest { - @Override - public boolean equals(final Object o) { - return o instanceof ConstructorTest; - } - } + public static final class ConstructorTest { + @Override + public boolean equals(final Object o) { + return o instanceof ConstructorTest; + } + } - @Test - public void testImplicitConstructor() { - Assert.assertEquals( - new ConstructorTest(), - new SpelHelper() - .registerImplicitConstructorsFromClass(ConstructorTest.class) - .evalExpression("new ConstructorTest()", new Object(), ConstructorTest.class)); - } + @Test + public void testImplicitConstructor() { + Assert.assertEquals( + new ConstructorTest(), + new SpelHelper() + .registerImplicitConstructorsFromClass(ConstructorTest.class) + .evalExpression("new ConstructorTest()", new Object(), ConstructorTest.class)); + } }