You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by mb...@apache.org on 2018/03/27 20:06:16 UTC
[4/4] bval git commit: handle multiple methods with same signature
per JLS 8
handle multiple methods with same signature per JLS 8
Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/65de7121
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/65de7121
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/65de7121
Branch: refs/heads/bv2
Commit: 65de71211d0ad8ff4be8b09402a00cc35b26e0f3
Parents: 7ea28b2
Author: Matt Benson <mb...@apache.org>
Authored: Tue Mar 27 15:03:57 2018 -0500
Committer: Matt Benson <mb...@apache.org>
Committed: Tue Mar 27 15:03:57 2018 -0500
----------------------------------------------------------------------
.../bval/jsr/metadata/ReflectionBuilder.java | 94 +++++++++++++++++---
.../org/apache/bval/jsr/metadata/Signature.java | 13 ++-
2 files changed, 93 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/bval/blob/65de7121/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
index 338e1d2..df8319b 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
@@ -30,12 +30,15 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
-import java.util.function.Function;
+import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@@ -43,6 +46,7 @@ import java.util.stream.Stream;
import javax.validation.ConstraintDeclarationException;
import javax.validation.ConstraintTarget;
import javax.validation.GroupSequence;
+import javax.validation.ParameterNameProvider;
import javax.validation.Valid;
import javax.validation.constraintvalidation.ValidationTarget;
import javax.validation.groups.ConvertGroup;
@@ -54,6 +58,7 @@ import org.apache.bval.jsr.util.AnnotationsManager;
import org.apache.bval.jsr.util.Methods;
import org.apache.bval.jsr.util.ToUnmodifiable;
import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Lazy;
import org.apache.bval.util.ObjectUtils;
import org.apache.bval.util.Validate;
import org.apache.bval.util.reflection.Reflection;
@@ -82,15 +87,42 @@ public class ReflectionBuilder {
if (declaredFields.length == 0) {
return Collections.emptyMap();
}
- return Stream.of(declaredFields).filter(f -> !Modifier.isStatic(f.getModifiers())).collect(
- Collectors.toMap(Field::getName, f -> new ReflectionBuilder.ForContainer<>(new Meta.ForField(f))));
+ return Stream.of(declaredFields).filter(f -> !(Modifier.isStatic(f.getModifiers()) || f.isSynthetic()))
+ .collect(
+ Collectors.toMap(Field::getName, f -> new ReflectionBuilder.ForContainer<>(new Meta.ForField(f))));
}
@Override
public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> ignored) {
- return Stream.of(Reflection.getDeclaredMethods(meta.getHost())).filter(Methods::isGetter)
- .collect(ToUnmodifiable.map(Methods::propertyName,
- g -> new ReflectionBuilder.ForContainer<>(new Meta.ForMethod(g))));
+ final Method[] declaredMethods = Reflection.getDeclaredMethods(meta.getHost());
+ if (declaredMethods.length == 0) {
+ return Collections.emptyMap();
+ }
+ final Map<String, Set<Method>> getters = new HashMap<>();
+ for (Method m : declaredMethods) {
+ if (Methods.isGetter(m)) {
+ getters.computeIfAbsent(Methods.propertyName(m), k -> new LinkedHashSet<>()).add(m);
+ }
+ }
+ final Map<String, MetadataBuilder.ForContainer<Method>> result = new TreeMap<>();
+ getters.forEach((k, methods) -> {
+ if ("class".equals(k)) {
+ return;
+ }
+ final List<MetadataBuilder.ForContainer<Method>> delegates = methods.stream()
+ .map(g -> new ReflectionBuilder.ForContainer<>(new Meta.ForMethod(g))).collect(Collectors.toList());
+ if (delegates.isEmpty()) {
+ return;
+ }
+ final MetadataBuilder.ForContainer<Method> builder;
+ if (delegates.size() == 1) {
+ builder = delegates.get(0);
+ } else {
+ builder = compositeBuilder.get().new ForContainer<>(delegates);
+ }
+ result.put(k, builder);
+ });
+ return result;
}
@Override
@@ -101,7 +133,7 @@ public class ReflectionBuilder {
}
return Stream.of(declaredConstructors).collect(
Collectors.toMap(Signature::of, c -> new ReflectionBuilder.ForExecutable<>(new Meta.ForConstructor<>(c),
- validatorFactory.getParameterNameProvider()::getParameterNames)));
+ ParameterNameProvider::getParameterNames)));
}
@Override
@@ -110,10 +142,33 @@ public class ReflectionBuilder {
if (declaredMethods.length == 0) {
return Collections.emptyMap();
}
+ final Map<Signature, Set<Method>> methodsBySignature = new HashMap<>();
+ for (Method m : declaredMethods) {
+ if (!Modifier.isStatic(m.getModifiers())) {
+ methodsBySignature.computeIfAbsent(Signature.of(m), k -> new LinkedHashSet<>()).add(m);
+ }
+ }
+ final Map<Signature, MetadataBuilder.ForExecutable<Method>> result = new TreeMap<>();
+
// we can't filter the getters since they can be validated, todo: read the config to know if we need or not
- return Stream.of(declaredMethods).collect(
- Collectors.toMap(Signature::of, m -> new ReflectionBuilder.ForExecutable<>(new Meta.ForMethod(m),
- validatorFactory.getParameterNameProvider()::getParameterNames)));
+
+ methodsBySignature.forEach((sig, methods) -> {
+ final List<MetadataBuilder.ForExecutable<Method>> delegates =
+ methods.stream().map(g -> new ReflectionBuilder.ForExecutable<>(new Meta.ForMethod(g),
+ ParameterNameProvider::getParameterNames)).collect(Collectors.toList());
+ if (delegates.isEmpty()) {
+ return;
+ }
+ final MetadataBuilder.ForExecutable<Method> builder;
+ if (delegates.size() == 1) {
+ builder = delegates.get(0);
+ } else {
+ builder = compositeBuilder.get().new ForExecutable<MetadataBuilder.ForExecutable<Method>, Method>(
+ delegates, ParameterNameProvider::getParameterNames);
+ }
+ result.put(sig, builder);
+ });
+ return result;
}
}
@@ -129,6 +184,16 @@ public class ReflectionBuilder {
public Annotation[] getDeclaredConstraints(Meta<E> ignored) {
return AnnotationsManager.getDeclaredConstraints(meta);
}
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj == this || this.getClass().isInstance(obj) && ((ForElement<?>) obj).meta.equals(meta);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getClass(), meta);
+ }
}
private class ForClass<T> extends ForElement<Class<T>> implements MetadataBuilder.ForClass<T> {
@@ -186,9 +251,9 @@ public class ReflectionBuilder {
private class ForExecutable<E extends Executable> implements MetadataBuilder.ForExecutable<E> {
final Meta<E> meta;
- final Function<E, List<String>> getParameterNames;
+ final BiFunction<ParameterNameProvider, E, List<String>> getParameterNames;
- ForExecutable(Meta<E> meta, Function<E, List<String>> getParameterNames) {
+ ForExecutable(Meta<E> meta, BiFunction<ParameterNameProvider,E, List<String>> getParameterNames) {
super();
this.meta = Validate.notNull(meta, "meta");
this.getParameterNames = Validate.notNull(getParameterNames, "getParameterNames");
@@ -200,7 +265,7 @@ public class ReflectionBuilder {
if (parameters.length == 0) {
return Collections.emptyList();
}
- final List<String> parameterNames = getParameterNames.apply(meta.getHost());
+ final List<String> parameterNames = getParameterNames.apply(validatorFactory.getParameterNameProvider(),meta.getHost());
return IntStream.range(0, parameters.length).mapToObj(
n -> new ReflectionBuilder.ForContainer<>(new Meta.ForParameter(parameters[n], parameterNames.get(n))))
@@ -296,10 +361,13 @@ public class ReflectionBuilder {
}
private final ApacheValidatorFactory validatorFactory;
+ private final Lazy<CompositeBuilder> compositeBuilder;
public ReflectionBuilder(ApacheValidatorFactory validatorFactory) {
super();
this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory");
+ this.compositeBuilder =
+ new Lazy<>(() -> new CompositeBuilder(this.validatorFactory, x -> AnnotationBehavior.ABSTAIN));
}
public <T> MetadataBuilder.ForBean<T> forBean(Class<T> beanClass) {
http://git-wip-us.apache.org/repos/asf/bval/blob/65de7121/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Signature.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Signature.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Signature.java
index 8def7ae..2f28a3e 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Signature.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Signature.java
@@ -18,17 +18,23 @@ package org.apache.bval.jsr.metadata;
import java.lang.reflect.Executable;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.bval.util.Comparators;
import org.apache.bval.util.Lazy;
import org.apache.bval.util.LazyInt;
import org.apache.bval.util.StringUtils;
import org.apache.bval.util.Validate;
-public final class Signature {
+public final class Signature implements Comparable<Signature> {
+ private static final Comparator<Signature> COMPARATOR = Comparator.nullsFirst(Comparator
+ .comparing(Signature::getName).thenComparing(Comparator.comparing(s -> Arrays.asList(s.getParameterTypes()),
+ Comparators.comparingIterables(Comparator.comparing(Class::getName)))));
+
public static Signature of(Executable x) {
return new Signature(x.getName(), x.getParameterTypes());
}
@@ -72,4 +78,9 @@ public final class Signature {
public String toString() {
return toString.get();
}
+
+ @Override
+ public int compareTo(Signature sig) {
+ return COMPARATOR.compare(this, sig);
+ }
}