DATACMNS-533 - Expose special parameters in SpEL expressions.

We now expose special parameters like Pageable and Sort to be used in SpEL expressions if they don't collide with existing named parameters.

Related pull request: spring-projects/spring-data-jpa#101
Related ticket: DATAJPA-564
This commit is contained in:
Thomas Darimont
2014-07-07 17:58:44 +02:00
committed by Oliver Gierke
parent d23e7baa2c
commit 31848f87eb
3 changed files with 96 additions and 8 deletions

View File

@@ -42,6 +42,7 @@ import org.springframework.expression.spel.SpelMessage;
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.TypeUtils;
/**
@@ -109,16 +110,53 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
// Add parameters for indexed access
ec.setRootObject(parameterValues);
// Add parameters as variables if named
for (Parameter param : parameters) {
if (param.isNamedParameter()) {
ec.setVariable(param.getName(), parameterValues[param.getIndex()]);
}
}
Map<String, Object> variables = collectVariables(parameters, parameterValues);
ec.setVariables(variables);
return ec;
}
protected <T extends Parameters<T, ? extends Parameter>> Map<String, Object> collectVariables(T parameters,
Object[] parameterValues) {
Map<String, Object> variables = new HashMap<String, Object>();
registerSpecialParameterVariablesIfPresent(parameters, parameterValues, variables);
registerNamedMethodParameterVariables(parameters, parameterValues, variables);
return variables;
}
protected <T extends Parameters<T, ? extends Parameter>> void registerNamedMethodParameterVariables(T parameters,
Object[] parameterValues, Map<String, Object> variables) {
for (Parameter param : parameters) {
if (param.isNamedParameter()) {
variables.put(param.getName(), parameterValues[param.getIndex()]);
}
}
}
protected <T extends Parameters<T, ? extends Parameter>> void registerSpecialParameterVariablesIfPresent(
T parameters, Object[] parameterValues, Map<String, Object> variables) {
if (parameters.hasSpecialParameter()) {
for (Parameter param : parameters) {
if (param.isSpecialParameter()) {
Object paramValue = parameterValues[param.getIndex()];
if (paramValue == null) {
continue;
}
variables.put(StringUtils.uncapitalize(param.getType().getSimpleName()), paramValue);
}
}
}
}
/**
* Returns the {@link EvaluationContextExtension} to be used. Either from the current configuration or the configured
* {@link BeanFactory}.
@@ -251,6 +289,10 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
final Method function = targetObject instanceof Map && ((Map<?, ?>) targetObject).containsKey(name) ? (Method) ((Map<?, ?>) targetObject)
.get(name) : (Method) functions.get(name);
if (function == null) {
return null;
}
Class<?>[] parameterTypes = function.getParameterTypes();
if (parameterTypes.length != argumentTypes.size()) {
return null;

View File

@@ -37,7 +37,7 @@ import org.springframework.util.Assert;
*/
public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter> implements Iterable<T> {
@SuppressWarnings("unchecked") public static final List<Class<?>> TYPES = Arrays.asList(Pageable.class, Sort.class);
public static final List<Class<?>> TYPES = Arrays.asList(Pageable.class, Sort.class);
private static final String PARAM_ON_SPECIAL = format("You must not user @%s on a parameter typed %s or %s",
Param.class.getSimpleName(), Pageable.class.getSimpleName(), Sort.class.getSimpleName());