From 4074f2e387b45dbb240191b465dda5ff22b91419 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sun, 21 Aug 2011 14:23:47 +0200 Subject: [PATCH] DATACMNS-61 - Refactored QueryMethod, Parameters and Parameter to be more open for extension. QueryMethod now provides a protected method to allow customization of the Parameters instance being used. Removed final modifier from Parameters and Parameter classes to allow extension. Refactored Parameter to be based on Spring's MethodParameter for more encapsulation. Added callback method to Parameters to allow customizing Parameter instance creation. Added protected method to ParametersParameterAccessor to get any parameter value by index. --- .../data/repository/query/Parameter.java | 48 ++++++++----------- .../data/repository/query/Parameters.java | 42 ++++------------ .../query/ParametersParameterAccessor.java | 11 +++++ .../data/repository/query/QueryMethod.java | 14 +++++- .../repository/query/ParametersUnitTests.java | 12 +++++ 5 files changed, 67 insertions(+), 60 deletions(-) diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameter.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameter.java index c1a4626f1..b02429fc3 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameter.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameter.java @@ -21,6 +21,7 @@ import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.List; +import org.springframework.core.MethodParameter; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.util.Assert; @@ -32,7 +33,7 @@ import org.springframework.util.Assert; * * @author Oliver Gierke */ -public final class Parameter { +public class Parameter { @SuppressWarnings("unchecked") static final List> TYPES = Arrays.asList(Pageable.class, @@ -46,11 +47,8 @@ public final class Parameter { private static final String NAMED_PARAMETER_TEMPLATE = ":%s"; private static final String POSITION_PARAMETER_TEMPLATE = "?%s"; - private final Class type; private final Parameters parameters; - private final int index; - private final String name; - + private final MethodParameter parameter; /** * Creates a new {@link Parameter} for the given type, {@link Annotation}s, @@ -61,16 +59,13 @@ public final class Parameter { * @param index * @param name */ - Parameter(Class type, Parameters parameters, int index, String name) { + protected Parameter(MethodParameter parameter, Parameters parameters) { - Assert.notNull(type); + Assert.notNull(parameter); Assert.notNull(parameters); + this.parameter = parameter; this.parameters = parameters; - this.index = index; - - this.type = type; - this.name = name; if (isSpecialParameter() && isNamedParameter()) { throw new IllegalArgumentException(PARAM_ON_SPECIAL); @@ -85,7 +80,7 @@ public final class Parameter { */ boolean isFirst() { - return index == 0; + return getIndex() == 0; } @@ -98,7 +93,7 @@ public final class Parameter { */ public Parameter getNext() { - return parameters.getParameter(index + 1); + return parameters.getParameter(getIndex() + 1); } @@ -109,7 +104,7 @@ public final class Parameter { */ Parameter getPrevious() { - return parameters.getParameter(index - 1); + return parameters.getParameter(getIndex() - 1); } @@ -122,7 +117,7 @@ public final class Parameter { */ public boolean isSpecialParameter() { - return TYPES.contains(type); + return TYPES.contains(parameter.getParameterType()); } @@ -162,7 +157,7 @@ public final class Parameter { */ public int getIndex() { - return index; + return parameter.getParameterIndex(); } @@ -185,8 +180,8 @@ public final class Parameter { * @return */ public String getName() { - - return name; + Param annotation = parameter.getParameterAnnotation(Param.class); + return annotation == null ? parameter.getParameterName() : annotation.value(); } @@ -196,19 +191,18 @@ public final class Parameter { * @return the type */ public Class getType() { - return type; + return parameter.getParameterType(); } /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ + * (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { - return format("%s:%s", isNamedParameter() ? getName() : "#" + index, - type.getName()); + return format("%s:%s", isNamedParameter() ? getName() : "#" + getIndex(), + getType().getName()); } @@ -219,7 +213,7 @@ public final class Parameter { */ boolean isPageable() { - return Pageable.class.isAssignableFrom(type); + return Pageable.class.isAssignableFrom(getType()); } @@ -230,6 +224,6 @@ public final class Parameter { */ boolean isSort() { - return Sort.class.isAssignableFrom(type); + return Sort.class.isAssignableFrom(getType()); } } diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java index bf0d3c59d..95788ea1c 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2010 the original author or authors. + * Copyright 2008-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package org.springframework.data.repository.query; -import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -23,6 +22,7 @@ import java.util.Iterator; import java.util.List; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -35,7 +35,7 @@ import org.springframework.util.Assert; * * @author Oliver Gierke */ -public final class Parameters implements Iterable { +public class Parameters implements Iterable { @SuppressWarnings("unchecked") public static final List> TYPES = Arrays.asList(Pageable.class, @@ -70,8 +70,9 @@ public final class Parameters implements Iterable { List> types = Arrays.asList(method.getParameterTypes()); for (int i = 0; i < types.size(); i++) { - String name = getParameterName(method, i); - parameters.add(new Parameter(types.get(i), this, i, name)); + MethodParameter parameter = new MethodParameter(method, i); + parameter.initParameterNameDiscovery(discoverer); + parameters.add(createParameter(parameter)); } this.pageableIndex = types.indexOf(Pageable.class); @@ -81,33 +82,6 @@ public final class Parameters implements Iterable { } - /** - * Returns the name of the parameter of the given {@link Method} with the - * given index. Inspects {@link Param} annotation before falling back to a - * {@link ParameterNameDiscoverer}. - * - * @param method - * @param index - * @return - */ - private String getParameterName(Method method, int index) { - - for (Annotation annotation : method.getParameterAnnotations()[index]) { - if (annotation instanceof Param) { - return ((Param) annotation).value(); - } - } - - String[] parameterNames = discoverer.getParameterNames(method); - - if (parameterNames != null) { - return parameterNames[index]; - } - - return null; - } - - /** * Creates a new {@link Parameters} instance with the given * {@link Parameter}s put into new context. @@ -133,6 +107,10 @@ public final class Parameters implements Iterable { this.pageableIndex = pageableIndexTemp; this.sortIndex = sortIndexTemp; } + + protected Parameter createParameter(MethodParameter parameter) { + return new Parameter(parameter, this); + } /** diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java index 64a4e9383..d44a288db 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java @@ -83,6 +83,17 @@ public class ParametersParameterAccessor implements ParameterAccessor { return null; } + + /** + * Returns the value with the given index. + * + * @param index + * @return + */ + @SuppressWarnings("unchecked") + protected T getValue(int index) { + return (T) values[index]; + } /* diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java index e2a3db1c4..bd4d21cf4 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -53,10 +53,12 @@ public class QueryMethod { * correct query to use for following invocations of the method given. * * @param method must not be {@literal null} + * @param metadata must not be {@literal null} */ public QueryMethod(Method method, RepositoryMetadata metadata) { Assert.notNull(method, "Method must not be null!"); + Assert.notNull(metadata, "Repository metadata must not be null!"); for (Class type : Parameters.TYPES) { if (getNumberOfOccurences(method, type) > 1) { @@ -76,9 +78,19 @@ public class QueryMethod { } this.method = method; - this.parameters = new Parameters(method); + this.parameters = getParameters(); this.metadata = metadata; } + + /** + * Creates a {@link Parameters} instance. + * + * @param method + * @return + */ + protected Parameters createParameters(Method method) { + return new Parameters(method); + } /** diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java index 13a022950..d6221883d 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java @@ -121,6 +121,18 @@ public class ParametersUnitTests { Parameters parameters = getParametersFor("emptyParameters"); assertThat(parameters.hasParameterAt(0), is(false)); } + + @Test + public void detectsPageableParameter() throws Exception { + Parameters parameters = getParametersFor("validWithPageable", String.class, Pageable.class); + assertThat(parameters.getPageableIndex(), is(1)); + } + + @Test + public void detectsSortParameter() throws Exception { + Parameters parameters = getParametersFor("validWithSort", String.class, Sort.class); + assertThat(parameters.getSortIndex(), is(1)); + } private Parameters getParametersFor(String methodName,