DATACMNS-1026 - Polishing.

Minor refactorings here in there for clarity.

Original pull request: #217.
This commit is contained in:
Oliver Gierke
2017-05-17 16:19:30 +02:00
parent 1bf318fb02
commit 0e36b43752
5 changed files with 37 additions and 30 deletions

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.repository.query;
import static org.springframework.data.util.StreamUtils.*;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -35,10 +37,10 @@ import org.springframework.data.repository.query.EvaluationContextExtensionInfor
import org.springframework.data.repository.query.Functions.NameAndArgumentCount;
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
import org.springframework.data.repository.query.spi.Function;
import org.springframework.data.util.MultiValueMapCollector;
import org.springframework.data.util.Streamable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldFilter;
@@ -55,6 +57,7 @@ import org.springframework.util.ReflectionUtils.MethodFilter;
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Jens Schauder
* @since 1.9
*/
class EvaluationContextExtensionInformation {
@@ -248,14 +251,11 @@ class EvaluationContextExtensionInformation {
* @return the methods
*/
public MultiValueMap<NameAndArgumentCount, Function> getFunctions(Optional<Object> target) {
return target.map(this::getFunctions).orElseGet(() -> new LinkedMultiValueMap<>());
}
return target.map( //
it -> methods.stream().collect( //
new MultiValueMapCollector<>( //
m -> NameAndArgumentCount.of(m), //
m -> new Function(m, it) //
))) //
.orElseGet(() -> CollectionUtils.toMultiValueMap(Collections.emptyMap()));
private MultiValueMap<NameAndArgumentCount, Function> getFunctions(Object target) {
return methods.stream().collect(toMultiMap(NameAndArgumentCount::of, m -> new Function(m, target)));
}
/**

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.data.repository.query;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Value;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -29,7 +29,7 @@ import java.util.stream.Stream;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.repository.query.spi.Function;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
@@ -38,18 +38,23 @@ import org.springframework.util.MultiValueMap;
* value lists are actually unique with respect to the signature.
*
* @author Jens Schauder
* @author Oliver Gierke
* @since 2.0
*/
class Functions {
private final MultiValueMap<NameAndArgumentCount, Function> functions = CollectionUtils
.toMultiValueMap(new HashMap<>());
private static final String MESSAGE_TEMPLATE = "There are multiple matching methods of name '%s' for parameter types (%s), but no "
+ "exact match. Make sure to provide only one matching overload or one with exactly those types.";
private final MultiValueMap<NameAndArgumentCount, Function> functions = new LinkedMultiValueMap<>();
void addAll(Map<String, Function> newFunctions) {
newFunctions.forEach((n, f) -> {
NameAndArgumentCount k = new NameAndArgumentCount(n, f.getParameterCount());
NameAndArgumentCount k = NameAndArgumentCount.of(n, f.getParameterCount());
List<Function> currentElements = get(k);
if (!contains(currentElements, f)) {
functions.add(k, f);
}
@@ -59,7 +64,9 @@ class Functions {
void addAll(MultiValueMap<NameAndArgumentCount, Function> newFunctions) {
newFunctions.forEach((k, list) -> {
List<Function> currentElements = get(k);
list.stream() //
.filter(f -> !contains(currentElements, f)) //
.forEach(f -> functions.add(k, f));
@@ -82,7 +89,7 @@ class Functions {
*/
Optional<Function> get(String name, List<TypeDescriptor> argumentTypes) {
Stream<Function> candidates = get(new NameAndArgumentCount(name, argumentTypes.size())).stream() //
Stream<Function> candidates = get(NameAndArgumentCount.of(name, argumentTypes.size())).stream() //
.filter(f -> f.supports(argumentTypes));
return bestMatch(candidates.collect(Collectors.toList()), argumentTypes);
}
@@ -96,11 +103,13 @@ class Functions {
if (candidates.isEmpty()) {
return Optional.empty();
}
if (candidates.size() == 1) {
return Optional.of(candidates.get(0));
}
Optional<Function> exactMatch = candidates.stream().filter(f -> f.supportsExact(argumentTypes)).findFirst();
if (!exactMatch.isPresent()) {
throw new IllegalStateException(createErrorMessage(candidates, argumentTypes));
}
@@ -110,24 +119,22 @@ class Functions {
private static String createErrorMessage(List<Function> candidates, List<TypeDescriptor> argumentTypes) {
String argumentTypeString = String.join( //
",", //
argumentTypes.stream().map(TypeDescriptor::getName).collect(Collectors.toList()));
String argumentTypeString = argumentTypes.stream()//
.map(TypeDescriptor::getName)//
.collect(Collectors.joining(","));
String messageTemplate = "There are multiple matching methods of name '%s' for parameter types (%s), but no "
+ "exact match. Make sure to provide only one matching overload or one with exactly those types.";
return String.format(messageTemplate, candidates.get(0).getName(), argumentTypeString);
return String.format(MESSAGE_TEMPLATE, candidates.get(0).getName(), argumentTypeString);
}
@Value
@AllArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE, staticName = "of")
static class NameAndArgumentCount {
String name;
int count;
static NameAndArgumentCount of(Method m) {
return new NameAndArgumentCount(m.getName(), m.getParameterCount());
return NameAndArgumentCount.of(m.getName(), m.getParameterCount());
}
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.util;
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@@ -36,11 +37,11 @@ import org.springframework.util.MultiValueMap;
* @author Jens Schauder
* @since 2.0
*/
@RequiredArgsConstructor
public class MultiValueMapCollector<T, K, V> implements Collector<T, MultiValueMap<K, V>, MultiValueMap<K, V>> {
@RequiredArgsConstructor(access = AccessLevel.PACKAGE, staticName = "of")
class MultiValueMapCollector<T, K, V> implements Collector<T, MultiValueMap<K, V>, MultiValueMap<K, V>> {
@NonNull private final Function<T, K> keyFunction;
@NonNull private final Function<T, V> valueFunction;
private final @NonNull Function<T, K> keyFunction;
private final @NonNull Function<T, V> valueFunction;
/*
* (non-Javadoc)

View File

@@ -88,6 +88,6 @@ public interface StreamUtils {
*/
public static <T, K, V> Collector<T, MultiValueMap<K, V>, MultiValueMap<K, V>> toMultiMap(Function<T, K> keyFunction,
Function<T, V> valueFunction) {
return new MultiValueMapCollector<T, K, V>(keyFunction, valueFunction);
return MultiValueMapCollector.of(keyFunction, valueFunction);
}
}

View File

@@ -29,7 +29,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.domain.PageRequest;
@@ -273,7 +272,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
.withMessageContaining("(java.lang.Integer)");
}
private ExtensionAwareEvaluationContextProvider createContextProviderWithOverloads() {
private static ExtensionAwareEvaluationContextProvider createContextProviderWithOverloads() {
return new ExtensionAwareEvaluationContextProvider(Collections.singletonList( //
new DummyExtension("_first", "first") {