Compare commits
6 Commits
SpelHelper
...
master
Author | SHA1 | Date |
---|---|---|
Abhinav Sarkar | f39d4eaf64 | |
Abhinav Sarkar | dfabc55c82 | |
Abhinav Sarkar | 9ebd8862d4 | |
Abhinav Sarkar | 410dcdada2 | |
Abhinav Sarkar | fc55ca72fb | |
Abhinav Sarkar | 2c3d0f10d9 |
20
README.mdown
20
README.mdown
|
@ -3,6 +3,18 @@ SpelHelper provides additional functionalities to work with
|
||||||
|
|
||||||
SpelHelper is available under GNU Lesser General Public License (GNU LGPL).
|
SpelHelper is available under GNU Lesser General Public License (GNU LGPL).
|
||||||
|
|
||||||
|
**Maven Usage**
|
||||||
|
|
||||||
|
To use SpelHelper with Maven, add the following snippet in the dependencies section of your project's POM file:
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.abhinavsarkar</groupId>
|
||||||
|
<artifactId>SpelHelper</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
**Functionalities**
|
||||||
|
|
||||||
The addition functionalities provided are:
|
The addition functionalities provided are:
|
||||||
|
|
||||||
1. Implicit methods
|
1. Implicit methods
|
||||||
|
@ -10,7 +22,7 @@ The addition functionalities provided are:
|
||||||
3. Simplified extension functions
|
3. Simplified extension functions
|
||||||
4. Simplified constructors
|
4. Simplified constructors
|
||||||
|
|
||||||
**Implicit Methods**
|
_**Implicit methods**_
|
||||||
|
|
||||||
Implicit methods allow one to registers methods with SpelHelper and attach
|
Implicit methods allow one to registers methods with SpelHelper and attach
|
||||||
them to particular classes. After that, when that method is called on an
|
them to particular classes. After that, when that method is called on an
|
||||||
|
@ -27,7 +39,7 @@ So when an expression like `"#list(1,4,2).sorted()"` is evaluated, the
|
||||||
first parameter and its return value is used in further evaluation of the
|
first parameter and its return value is used in further evaluation of the
|
||||||
expression.
|
expression.
|
||||||
|
|
||||||
**Implicit Properties**
|
_**Implicit properties**_
|
||||||
|
|
||||||
Implicit properties allow one to treat no argument methods of an object
|
Implicit properties allow one to treat no argument methods of an object
|
||||||
as properties of the object. SpelHelper intercepts the property resolution
|
as properties of the object. SpelHelper intercepts the property resolution
|
||||||
|
@ -42,7 +54,7 @@ the same value as the last example.
|
||||||
Implicit property resolution considers both the actual methods of the object
|
Implicit property resolution considers both the actual methods of the object
|
||||||
and the implicit methods registered on the object's class.
|
and the implicit methods registered on the object's class.
|
||||||
|
|
||||||
**Simplified extension functions**
|
_**Simplified extension functions**_
|
||||||
|
|
||||||
SpEL [allows][2] to register extension function on the context by providing a
|
SpEL [allows][2] to register extension function on the context by providing a
|
||||||
name and a java.lang.reflect.Method object. SpelHelper simplifies this by taking a class
|
name and a java.lang.reflect.Method object. SpelHelper simplifies this by taking a class
|
||||||
|
@ -54,7 +66,7 @@ registered by SpelHelper. Hence the method [ExtensionFunctions#list(Object...)][
|
||||||
can be called from inside a SpEL expression using the function call syntax:
|
can be called from inside a SpEL expression using the function call syntax:
|
||||||
`"#list(1,2,3)`".
|
`"#list(1,2,3)`".
|
||||||
|
|
||||||
**Simplified constructors**
|
_**Simplified constructors**_
|
||||||
|
|
||||||
SpEL [allows][3] calling constructors from inside a SpEL expression using the
|
SpEL [allows][3] calling constructors from inside a SpEL expression using the
|
||||||
`new` operator. But they have to be called with their full name like:
|
`new` operator. But they have to be called with their full name like:
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<groupId>net.abhinavsarkar</groupId>
|
<groupId>net.abhinavsarkar</groupId>
|
||||||
<artifactId>SpelHelper</artifactId>
|
<artifactId>SpelHelper</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.3-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>SpelHelper</name>
|
<name>SpelHelper</name>
|
||||||
|
|
|
@ -27,8 +27,7 @@ import org.springframework.expression.ConstructorResolver;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
|
import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
|
||||||
|
|
||||||
final class ImplicitConstructorResolver implements
|
final class ImplicitConstructorResolver implements ConstructorResolver {
|
||||||
ConstructorResolver {
|
|
||||||
|
|
||||||
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
|
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
|
||||||
|
|
||||||
|
|
|
@ -39,20 +39,21 @@ final class ImplicitMethodResolver implements MethodResolver {
|
||||||
private final ReflectiveMethodResolver delegate = new ReflectiveMethodResolver();
|
private final ReflectiveMethodResolver delegate = new ReflectiveMethodResolver();
|
||||||
|
|
||||||
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
||||||
|
@Override
|
||||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||||
final Object... arguments) throws AccessException {
|
final Object... arguments) throws AccessException {
|
||||||
return null;
|
throw new UnsupportedOperationException("This method should never be called");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final class ImplicitMethodExecutor implements
|
private static final class ImplicitMethodExecutor implements MethodExecutor {
|
||||||
MethodExecutor {
|
|
||||||
private final MethodExecutor executor;
|
private final MethodExecutor executor;
|
||||||
|
|
||||||
public ImplicitMethodExecutor(final MethodExecutor executor) {
|
public ImplicitMethodExecutor(final MethodExecutor executor) {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||||
final Object... arguments) throws AccessException {
|
final Object... arguments) throws AccessException {
|
||||||
Object[] modifiedArguments = new Object[arguments.length + 1];
|
Object[] modifiedArguments = new Object[arguments.length + 1];
|
||||||
|
@ -66,7 +67,7 @@ final class ImplicitMethodResolver implements MethodResolver {
|
||||||
public MethodExecutor resolve(
|
public MethodExecutor resolve(
|
||||||
final EvaluationContext context, final Object targetObject,
|
final EvaluationContext context, final Object targetObject,
|
||||||
final String name, final List<TypeDescriptor> argumentTypes)
|
final String name, final List<TypeDescriptor> argumentTypes)
|
||||||
throws AccessException {
|
throws AccessException {
|
||||||
if (targetObject == null) {
|
if (targetObject == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,13 +34,22 @@ final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
||||||
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
||||||
new ConcurrentHashMap<String, MethodExecutor>();
|
new ConcurrentHashMap<String, MethodExecutor>();
|
||||||
|
|
||||||
|
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
||||||
|
@Override
|
||||||
|
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||||
|
final Object... arguments) throws AccessException {
|
||||||
|
throw new UnsupportedOperationException("This method should never be called");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean canRead(final EvaluationContext context,
|
public boolean canRead(final EvaluationContext context,
|
||||||
final Object target, final String name)
|
final Object target, final String name)
|
||||||
throws AccessException {
|
throws AccessException {
|
||||||
Assert.notNull(target, "target is null");
|
Assert.notNull(target, "target is null");
|
||||||
String cacheKey = target.getClass().getName() + "." + name;
|
String cacheKey = target.getClass().getName() + "." + name;
|
||||||
if (CACHE.containsKey(cacheKey)) {
|
if (CACHE.containsKey(cacheKey)) {
|
||||||
return CACHE.get(cacheKey) != null;
|
return CACHE.get(cacheKey) != NULL_ME;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MethodResolver mr : context.getMethodResolvers()) {
|
for (MethodResolver mr : context.getMethodResolvers()) {
|
||||||
|
@ -52,10 +61,11 @@ final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CACHE.putIfAbsent(cacheKey, null);
|
CACHE.putIfAbsent(cacheKey, NULL_ME);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TypedValue read(final EvaluationContext context,
|
public TypedValue read(final EvaluationContext context,
|
||||||
final Object target, final String name)
|
final Object target, final String name)
|
||||||
throws AccessException {
|
throws AccessException {
|
||||||
|
|
|
@ -23,19 +23,21 @@ import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.PropertyAccessor;
|
import org.springframework.expression.PropertyAccessor;
|
||||||
|
|
||||||
abstract class ReadOnlyGenericPropertyAccessor implements
|
abstract class ReadOnlyGenericPropertyAccessor implements PropertyAccessor {
|
||||||
PropertyAccessor {
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public final boolean canWrite(final EvaluationContext context,
|
public final boolean canWrite(final EvaluationContext context,
|
||||||
final Object target, final String name) throws AccessException {
|
final Object target, final String name) throws AccessException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public final Class[] getSpecificTargetClasses() {
|
public final Class[] getSpecificTargetClasses() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void write(final EvaluationContext context, final Object target,
|
public final void write(final EvaluationContext context, final Object target,
|
||||||
final String name, final Object newValue) throws AccessException {
|
final String name, final Object newValue) throws AccessException {
|
||||||
throw new AccessException(MessageFormat.format(
|
throw new AccessException(MessageFormat.format(
|
||||||
|
|
Loading…
Reference in New Issue