code updates
Project: http://git-wip-us.apache.org/repos/asf/bval/repo Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/f87be824 Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/f87be824 Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/f87be824 Branch: refs/heads/bv2 Commit: f87be824d77a26424e6856183391c8d3340b5241 Parents: b808381 Author: Matt Benson <[email protected]> Authored: Wed Feb 21 14:58:35 2018 -0600 Committer: Matt Benson <[email protected]> Committed: Wed Feb 21 14:59:59 2018 -0600 ---------------------------------------------------------------------- .../bval/routines/EMailValidationUtils.java | 7 +- .../main/java/org/apache/bval/el/ELFacade.java | 16 +-- .../bval/jsr/AnnotationConstraintBuilder.java | 38 ++--- .../apache/bval/jsr/AnnotationProcessor.java | 24 ++-- .../jsr/ConstraintAnnotationAttributes.java | 46 +++--- .../org/apache/bval/jsr/ConstraintCached.java | 143 +++++++++++++++++-- .../org/apache/bval/jsr/ConstraintDefaults.java | 103 +++++-------- .../bval/jsr/ConstraintDescriptorImpl.java | 13 ++ .../apache/bval/jsr/ConstraintValidation.java | 33 ++++- .../jsr/ConstraintValidatorContextImpl.java | 20 ++- .../bval/jsr/ConstraintValidatorIdentity.java | 9 +- .../bval/jsr/ConstraintViolationImpl.java | 94 +++++------- .../jsr/DefaultConstraintValidatorFactory.java | 12 +- .../bval/jsr/DefaultMessageInterpolator.java | 35 ++--- .../jsr/DefaultValidationProviderResolver.java | 50 +++---- .../org/apache/bval/jsr/GraphBeanIdentity.java | 28 +--- .../bval/jsr/ParameterDescriptorImpl.java | 7 + .../apache/bval/jsr/PropertyDescriptorImpl.java | 9 ++ .../bval/jsr/ReturnValueDescriptorImpl.java | 8 ++ .../java/org/apache/bval/jsr/groups/Group.java | 13 +- .../groups/GroupConversionDescriptorImpl.java | 3 +- .../java/org/apache/bval/jsr/groups/Groups.java | 67 +++++---- .../apache/bval/jsr/groups/GroupsComputer.java | 111 +++++++------- .../parameter/DefaultParameterNameProvider.java | 25 ++-- .../resolver/CachingTraversableResolver.java | 26 ++-- 25 files changed, 506 insertions(+), 434 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java ---------------------------------------------------------------------- diff --git a/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java b/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java index 1158c7f..0835bae 100644 --- a/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java +++ b/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java @@ -29,12 +29,11 @@ public class EMailValidationUtils { private static String ATOM = "[^\\x00-\\x1F\\(\\)\\<\\>\\@\\,\\;\\:\\\\\\\"\\.\\[\\]\\s]"; private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*"; private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]"; - public static final java.util.regex.Pattern DEFAULT_EMAIL_PATTERN; + public static final Pattern DEFAULT_EMAIL_PATTERN; static { - DEFAULT_EMAIL_PATTERN = - java.util.regex.Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$", - java.util.regex.Pattern.CASE_INSENSITIVE); + DEFAULT_EMAIL_PATTERN = Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$", + Pattern.CASE_INSENSITIVE); } /** http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java b/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java index 49f236b..9798455 100644 --- a/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java +++ b/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java @@ -54,10 +54,9 @@ public final class ELFacade implements MessageEvaluator { if (EXPRESSION_FACTORY != null) { final BValELContext context = new BValELContext(); final VariableMapper variables = context.getVariableMapper(); - for (final Map.Entry<String, Object> var : annotationParameters.entrySet()) { - variables.setVariable(var.getKey(), - EXPRESSION_FACTORY.createValueExpression(var.getValue(), Object.class)); - } + annotationParameters.forEach( + (k, v) -> variables.setVariable(k, EXPRESSION_FACTORY.createValueExpression(v, Object.class))); + variables.setVariable("validatedValue", EXPRESSION_FACTORY.createValueExpression(validatedValue, Object.class)); @@ -83,13 +82,8 @@ public final class ELFacade implements MessageEvaluator { } private static class BValELContext extends ELContext { - private final FunctionMapper functions; - private final VariableMapper variables; - - public BValELContext() { - this.variables = new BValVariableMapper(); - this.functions = new BValFunctionMapper(); - } + private final FunctionMapper functions = new BValFunctionMapper(); + private final VariableMapper variables = new BValVariableMapper(); @Override public ELResolver getELResolver() { http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java index 017cabb..4b15ba7 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java @@ -72,7 +72,7 @@ final class AnnotationConstraintBuilder<A extends Annotation> { final boolean reportFromComposite = annotation != null && annotation.annotationType().isAnnotationPresent(ReportAsSingleViolation.class); constraintValidation = - new ConstraintValidation<A>(validatorClasses, annotation, owner, access, reportFromComposite, target); + new ConstraintValidation<>(validatorClasses, annotation, owner, access, reportFromComposite, target); buildFromAnnotation(); } @@ -139,7 +139,7 @@ final class AnnotationConstraintBuilder<A extends Annotation> { if (!foundGroups) { throw new ConstraintDefinitionException("Annotation " + annotationType.getName() + " has no groups method"); } - if (validationAppliesTo != null && !ConstraintTarget.IMPLICIT.equals(validationAppliesTo.getDefaultValue())) { + if (validationAppliesTo != null && ConstraintTarget.IMPLICIT != validationAppliesTo.getDefaultValue()) { throw new ConstraintDefinitionException("validationAppliesTo default value should be IMPLICIT"); } @@ -257,9 +257,9 @@ final class AnnotationConstraintBuilder<A extends Annotation> { final Set<Class<? extends Payload>> payloadSet; if (payload_raw == null) { - payloadSet = Collections.<Class<? extends Payload>> emptySet(); + payloadSet = Collections.emptySet(); } else { - payloadSet = new HashSet<Class<? extends Payload>>(payload_raw.length); + payloadSet = new HashSet<>(payload_raw.length); Collections.addAll(payloadSet, payload_raw); } constraintValidation.setPayload(payloadSet); @@ -323,18 +323,13 @@ final class AnnotationConstraintBuilder<A extends Annotation> { * @return An integer index always >= 0 */ private int computeIndex(ConstraintValidation<?> composite) { - int idx = 0; - for (ConstraintValidation<?> each : constraintValidation.getComposingValidations()) { - if (each.getAnnotation().annotationType() == composite.getAnnotation().annotationType()) { - idx++; - } - } - return idx; + return (int) constraintValidation.getComposingValidations().stream() + .filter(v -> v.getAnnotation().annotationType().equals(composite.getAnnotation().annotationType())).count(); } /** read overridesAttributes from constraintValidation.annotation */ private void buildOverridesAttributes() { - overrides = new LinkedList<ConstraintOverrides>(); + overrides = new LinkedList<>(); for (Method method : constraintValidation.getAnnotation().annotationType().getDeclaredMethods()) { final OverridesAttribute.List overridesAttributeList = method.getAnnotation(OverridesAttribute.List.class); if (overridesAttributeList != null) { @@ -359,12 +354,9 @@ final class AnnotationConstraintBuilder<A extends Annotation> { } private ConstraintOverrides findOverride(Class<? extends Annotation> constraint, int constraintIndex) { - for (ConstraintOverrides each : overrides) { - if (each.constraintType == constraint && each.constraintIndex == constraintIndex) { - return each; - } - } - return null; + return overrides.stream() + .filter(ov -> ov.constraintType.equals(constraint) && ov.constraintIndex == constraintIndex).findFirst() + .orElse(null); } /** @@ -381,7 +373,7 @@ final class AnnotationConstraintBuilder<A extends Annotation> { private ConstraintOverrides(Class<? extends Annotation> constraintType, int constraintIndex) { this.constraintType = constraintType; this.constraintIndex = constraintIndex; - values = new HashMap<String, Object>(); + values = new HashMap<>(); } @SuppressWarnings("unchecked") @@ -392,11 +384,9 @@ final class AnnotationConstraintBuilder<A extends Annotation> { // And the annotation final Annotation originalAnnot = composite.getAnnotation(); final AnnotationProxyBuilder<Annotation> apb = new AnnotationProxyBuilder<Annotation>(originalAnnot); - for (String key : values.keySet()) { - apb.putValue(key, values.get(key)); - } - final Annotation newAnnot = apb.createAnnotation(); - ((ConstraintValidation<Annotation>) composite).setAnnotation(newAnnot); + values.forEach(apb::putValue); + + ((ConstraintValidation<Annotation>) composite).setAnnotation(apb.createAnnotation()); } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java index 4bdb331..3c4b046 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java @@ -38,7 +38,9 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Set; /** @@ -121,7 +123,7 @@ public final class AnnotationProcessor { if (!reflection) { Collection<Annotation> annotations = prop.getFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS); if (annotations == null) { - annotations = new ArrayList<Annotation>(); + annotations = new ArrayList<>(); prop.putFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS, annotations); } annotations.add(annotation); @@ -129,18 +131,19 @@ public final class AnnotationProcessor { return true; } - /** + /* * An annotation is considered a constraint definition if its retention * policy contains RUNTIME and if the annotation itself is annotated * with javax.validation.Constraint. */ final Constraint vcAnno = annotation.annotationType().getAnnotation(Constraint.class); if (vcAnno != null) { - Class<? extends ConstraintValidator<A, ?>>[] validatorClasses; - validatorClasses = findConstraintValidatorClasses(annotation, vcAnno); + Class<? extends ConstraintValidator<A, ?>>[] validatorClasses = + findConstraintValidatorClasses(annotation, vcAnno); return applyConstraint(annotation, validatorClasses, prop, owner, access, appender); } - /** + + /* * Multi-valued constraints: To support this requirement, the bean * validation provider treats regular annotations (annotations not * annotated by @Constraint) whose value element has a return type of an @@ -202,15 +205,14 @@ public final class AnnotationProcessor { vcAnno = annotation.annotationType().getAnnotation(Constraint.class); } final Class<A> annotationType = (Class<A>) annotation.annotationType(); - Class<? extends ConstraintValidator<A, ?>>[] validatorClasses = - factory.getConstraintsCache().getConstraintValidators(annotationType); + List<Class<? extends ConstraintValidator<A, ?>>> validatorClasses = + factory.getConstraintsCache().getConstraintValidatorClasses(annotationType); if (validatorClasses == null) { - validatorClasses = (Class<? extends ConstraintValidator<A, ?>>[]) vcAnno.validatedBy(); - if (validatorClasses.length == 0) { - validatorClasses = factory.getDefaultConstraints().getValidatorClasses(annotationType); + validatorClasses = Arrays.asList((Class<? extends ConstraintValidator<A, ?>>[]) vcAnno.validatedBy()); + if (validatorClasses.isEmpty()) { } } - return validatorClasses; + return validatorClasses.toArray(new Class[validatorClasses.size()]); } /** http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java index 24b38ea..df99bf9 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java @@ -16,6 +16,7 @@ */ package org.apache.bval.jsr; +import org.apache.bval.util.Exceptions; import org.apache.bval.util.reflection.Reflection; import org.apache.bval.util.reflection.TypeUtils; import org.apache.commons.weaver.privilizer.Privilizing; @@ -125,29 +126,24 @@ public enum ConstraintAnnotationAttributes { public <V> V get(Map<? super String, ? super V> map) { @SuppressWarnings("unchecked") final V result = (V) map.get(getAttributeName()); - if (TypeUtils.isInstance(result, getType())) { - return result; - } - throw new IllegalStateException(String.format("Invalid '%s' value: %s", getAttributeName(), result)); + Exceptions.raiseUnless(TypeUtils.isInstance(result, getType()), IllegalStateException::new, + "Invalid '%s' value: %s", getAttributeName(), result); + return result; } public <C extends Annotation> Worker<C> analyze(final Class<C> clazz) { if (clazz.getName().startsWith("javax.validation.constraint.")) { // cache only APIs classes to avoid memory leaks @SuppressWarnings("unchecked") - Worker<C> w = Worker.class.cast(WORKER_CACHE.get(clazz)); - if (w == null) { - w = new Worker<C>(clazz); - WORKER_CACHE.putIfAbsent(clazz, w); - return w; - } + final Worker<C> w = (Worker<C>) WORKER_CACHE.computeIfAbsent(clazz, Worker::new); + return w; } return new Worker<C>(clazz); } // this is static but related to Worker - private static final ConcurrentMap<Class<?>, Worker<?>> WORKER_CACHE = new ConcurrentHashMap<Class<?>, Worker<?>>(); + private static final ConcurrentMap<Class<?>, Worker<?>> WORKER_CACHE = new ConcurrentHashMap<>(); private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Method>> METHOD_BY_NAME_AND_CLASS = - new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Method>>(); + new ConcurrentHashMap<>(); private static final Method NULL_METHOD; static { try { @@ -171,14 +167,8 @@ public enum ConstraintAnnotationAttributes { } private Method findMethod(final Class<C> constraintType, final String attributeName) { - ConcurrentMap<String, Method> cache = METHOD_BY_NAME_AND_CLASS.get(constraintType); - if (cache == null) { - cache = new ConcurrentHashMap<String, Method>(); - final ConcurrentMap<String, Method> old = METHOD_BY_NAME_AND_CLASS.putIfAbsent(constraintType, cache); - if (old != null) { - cache = old; - } - } + ConcurrentMap<String, Method> cache = + METHOD_BY_NAME_AND_CLASS.computeIfAbsent(constraintType, t -> new ConcurrentHashMap<>()); final Method found = cache.get(attributeName); if (found != null) { @@ -189,15 +179,19 @@ public enum ConstraintAnnotationAttributes { cache.putIfAbsent(attributeName, NULL_METHOD); return null; } - final Method oldMtd = cache.putIfAbsent(attributeName, m); - if (oldMtd != null) { - return oldMtd; - } - return m; + return cache.computeIfAbsent(attributeName, s -> m); } public boolean isValid() { - return method != null && method != NULL_METHOD; + return method != null && method != NULL_METHOD && TypeUtils.isAssignable(method.getReturnType(), type); + } + + /** + * @since 2.0 + * @return {@link Type} + */ + public Type getSpecificType() { + return isValid() ? method.getGenericReturnType() : type; } public <T> T read(final Annotation constraint) { http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java index 1bb012f..a1f3924 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java @@ -18,18 +18,92 @@ */ package org.apache.bval.jsr; -import javax.validation.ConstraintValidator; import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.validation.ConstraintValidator; +import javax.validation.constraintvalidation.SupportedValidationTarget; +import javax.validation.constraintvalidation.ValidationTarget; + +import org.apache.bval.jsr.metadata.AnnotationDeclaredValidatorMappingProvider; +import org.apache.bval.jsr.metadata.CompositeValidatorMappingProvider; +import org.apache.bval.jsr.metadata.DualValidationMappingProvider; +import org.apache.bval.jsr.metadata.ValidatorMappingProvider; +import org.apache.bval.jsr.util.ToUnmodifiable; +import org.apache.bval.util.Lazy; +import org.apache.bval.util.ObjectUtils; +import org.apache.bval.util.Validate; /** - * Description: hold the relationship annotation->validatedBy[] ConstraintValidator classes that are already parsed in a - * cache.<br/> + * Description: hold the relationship annotation->validatedBy[] + * ConstraintValidator classes that are already parsed in a cache.<br/> */ public class ConstraintCached { - private final Map<Class<? extends Annotation>, Class<? extends ConstraintValidator<?, ?>>[]> classes = - new HashMap<Class<? extends Annotation>, Class<? extends ConstraintValidator<?, ?>>[]>(); + + /** + * Describes a {@link ConstraintValidator} implementation type. + * + * @since 2.0 + */ + public static final class ConstraintValidatorInfo<T extends Annotation> { + private static final Set<ValidationTarget> DEFAULT_VALIDATION_TARGETS = + Collections.singleton(ValidationTarget.ANNOTATED_ELEMENT); + + private final Class<? extends ConstraintValidator<T, ?>> type; + private Set<ValidationTarget> supportedTargets; + + ConstraintValidatorInfo(Class<? extends ConstraintValidator<T, ?>> type) { + super(); + this.type = Validate.notNull(type); + final SupportedValidationTarget svt = type.getAnnotation(SupportedValidationTarget.class); + + supportedTargets = svt == null ? DEFAULT_VALIDATION_TARGETS + : Collections.unmodifiableSet(EnumSet.copyOf(Arrays.asList(svt.value()))); + } + + public Class<? extends ConstraintValidator<T, ?>> getType() { + return type; + } + + public Set<ValidationTarget> getSupportedTargets() { + return supportedTargets; + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj instanceof ConstraintValidatorInfo<?> && ((ConstraintValidatorInfo<?>) obj).type.equals(type); + } + + @Override + public int hashCode() { + return Objects.hash(type); + } + } + + private final Map<Class<? extends Annotation>, Set<ConstraintValidatorInfo<?>>> constraintValidatorInfo = + new HashMap<>(); + + private final List<ValidatorMappingProvider> customValidatorMappingProviders = new ArrayList<>(); + private final Lazy<ValidatorMappingProvider> validatorMappingProvider = + new Lazy<>(this::createValidatorMappingProvider); + + public void add(ValidatorMappingProvider validatorMappingProvider) { + if (customValidatorMappingProviders.add(validatorMappingProvider)) { + this.validatorMappingProvider.reset(this::createValidatorMappingProvider); + } + } /** * Record the set of validator classes for a given constraint annotation. @@ -37,33 +111,80 @@ public class ConstraintCached { * @param annotationClass * @param definitionClasses */ + @Deprecated public <A extends Annotation> void putConstraintValidator(Class<A> annotationClass, Class<? extends ConstraintValidator<A, ?>>[] definitionClasses) { - classes.put(annotationClass, definitionClasses); + if (ObjectUtils.isEmpty(definitionClasses)) { + return; + } + Validate.notNull(annotationClass, "annotationClass"); + Stream.of(definitionClasses).map(t -> new ConstraintValidatorInfo<>(t)) + .forEach(constraintValidatorInfo.computeIfAbsent(annotationClass, k -> new HashSet<>())::add); } /** - * Learn whether we have cached the validator classes for the requested constraint annotation. + * Learn whether we have cached the validator classes for the requested + * constraint annotation. * * @param annotationClass * to look up * @return boolean */ + @Deprecated public boolean containsConstraintValidator(Class<? extends Annotation> annotationClass) { - return classes.containsKey(annotationClass); + return constraintValidatorInfo.containsKey(annotationClass); } /** * Get the cached validator classes for the requested constraint annotation. * - * @param annotationClass + * @param constraintType * to look up * @return array of {@link ConstraintValidator} implementation types */ @SuppressWarnings("unchecked") + @Deprecated public <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] getConstraintValidators( - Class<A> annotationClass) { - return (Class<? extends ConstraintValidator<A, ?>>[]) classes.get(annotationClass); + Class<A> constraintType) { + final Set<ConstraintValidatorInfo<A>> infos = infos(constraintType); + return infos == null ? new Class[0] + : infos.stream().map(ConstraintValidatorInfo::getType).toArray(Class[]::new); } + public <A extends Annotation> List<Class<? extends ConstraintValidator<A, ?>>> getConstraintValidatorClasses( + Class<A> constraintType) { + final Set<ConstraintValidatorInfo<A>> infos = infos(constraintType); + return infos == null ? Collections.emptyList() + : infos.stream().map(ConstraintValidatorInfo::getType).collect(ToUnmodifiable.list()); + } + + public <A extends Annotation> Set<ConstraintValidatorInfo<A>> getConstraintValidatorInfo(Class<A> constraintType) { + return Collections.unmodifiableSet(infos(constraintType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private <A extends Annotation> Set<ConstraintValidatorInfo<A>> infos(Class<A> constraintType) { + return (Set) constraintValidatorInfo.computeIfAbsent(constraintType, + c -> validatorMappingProvider.get().getValidatorMapping(c).getValidatorTypes().stream() + .map(ConstraintValidatorInfo::new).collect(Collectors.toSet())); + } + + private ValidatorMappingProvider createValidatorMappingProvider() { + final ValidatorMappingProvider configured; + if (customValidatorMappingProviders.isEmpty()) { + configured = AnnotationDeclaredValidatorMappingProvider.INSTANCE; + } else { + final ValidatorMappingProvider custom; + if (customValidatorMappingProviders.size() == 1) { + custom = customValidatorMappingProviders.get(0); + } else { + custom = new CompositeValidatorMappingProvider(customValidatorMappingProviders); + } + configured = new DualValidationMappingProvider(AnnotationDeclaredValidatorMappingProvider.INSTANCE, custom); + } + // interpret spec as saying that default constraint validators are + // always present even when annotation-based validators + // have been excluded by custom (i.e. XML) config: + return new DualValidationMappingProvider(configured, ConstraintDefaults.INSTANCE); + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java index 3e3771e..9ea93e7 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java @@ -21,101 +21,70 @@ package org.apache.bval.jsr; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.validation.ConstraintValidator; +import org.apache.bval.jsr.metadata.ClassLoadingValidatorMappingProvider; +import org.apache.bval.jsr.metadata.ValidatorMapping; import org.apache.bval.util.StringUtils; import org.apache.bval.util.reflection.Reflection; import org.apache.commons.weaver.privilizer.Privilizing; import org.apache.commons.weaver.privilizer.Privilizing.CallTo; /** - * Description: Provides access to the default constraints/validator implementation classes built into the framework. - * These are configured in DefaultConstraints.properties.<br/> + * Description: Provides access to the default constraints/validator + * implementation classes built into the framework. These are configured in + * DefaultConstraints.properties.<br/> */ @Privilizing(@CallTo(Reflection.class)) -public class ConstraintDefaults { +public class ConstraintDefaults extends ClassLoadingValidatorMappingProvider { + public static final ConstraintDefaults INSTANCE = new ConstraintDefaults(); + private static final Logger log = Logger.getLogger(ConstraintDefaults.class.getName()); private static final String DEFAULT_CONSTRAINTS = "org/apache/bval/jsr/DefaultConstraints.properties"; - /** - * The default constraint data stored herein. - */ - private Map<String, Class<? extends ConstraintValidator<?, ?>>[]> defaultConstraints; + private final Properties properties; /** * Create a new ConstraintDefaults instance. */ - public ConstraintDefaults() { - defaultConstraints = loadDefaultConstraints(DEFAULT_CONSTRAINTS); - } - - /** - * Get the default constraint data. - * @return String-keyed map - */ - public Map<String, Class<? extends ConstraintValidator<?, ?>>[]> getDefaultConstraints() { - return defaultConstraints; - } - - /** - * Get the default validator implementation types for the specified constraint annotation type. - * @param annotationType the annotation type - * @return array of {@link ConstraintValidator} implementation classes - */ - @SuppressWarnings("unchecked") - public <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] getValidatorClasses( - Class<A> annotationType) { - return (Class<? extends ConstraintValidator<A, ?>>[]) getDefaultConstraints().get(annotationType.getName()); + private ConstraintDefaults() { + this.properties = loadProperties(DEFAULT_CONSTRAINTS); } - @SuppressWarnings("unchecked") - private Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadDefaultConstraints(String resource) { - final Properties constraintProperties = new Properties(); + private Properties loadProperties(String resource) { + final Properties result = new Properties(); final ClassLoader classloader = getClassLoader(); - final InputStream stream = classloader.getResourceAsStream(resource); - if (stream == null) { - log.log(Level.WARNING, String.format("Cannot find %s", resource)); - } else { - try { - constraintProperties.load(stream); - } catch (IOException e) { - log.log(Level.SEVERE, String.format("Cannot load %s", resource), e); - } finally { - try { - stream.close(); - } catch (final IOException e) { - // no-op - } + try (final InputStream stream = classloader.getResourceAsStream(resource)) { + if (stream == null) { + log.log(Level.WARNING, String.format("Cannot find %s", resource)); + } else { + result.load(stream); } + } catch (IOException e) { + log.log(Level.SEVERE, String.format("Cannot load %s", resource), e); } + return result; + } - final Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadedConstraints = - new HashMap<String, Class<? extends ConstraintValidator<?, ?>>[]>(); + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public <A extends Annotation> ValidatorMapping<A> doGetValidatorMapping(Class<A> constraintType) { - for (final Map.Entry<Object, Object> entry : constraintProperties.entrySet()) { - final List<Class<?>> classes = new LinkedList<Class<?>>(); - for (String className : StringUtils.split((String) entry.getValue(), ',')) { - try { - classes.add(Reflection.toClass(className.trim(), classloader)); - } catch (Exception e) { - log.log(Level.SEVERE, String.format("Cannot find class %s", className), e); - } - } - loadedConstraints.put((String) entry.getKey(), classes.toArray(new Class[classes.size()])); - } - return loadedConstraints; - } + final String validators = properties.getProperty(constraintType.getName()); - private ClassLoader getClassLoader() { - final ClassLoader classloader = Thread.currentThread().getContextClassLoader(); - return classloader == null ? getClass().getClassLoader() : classloader; + if (StringUtils.isBlank(validators)) { + return null; + } + return new ValidatorMapping<>("built-in", + load(Stream.of(StringUtils.split(validators, ',')).map(String::trim), + (Class<ConstraintValidator<A, ?>>) (Class) ConstraintValidator.class, + e -> log.log(Level.SEVERE, "exception loading default constraint validators", e)) + .collect(Collectors.toList())); } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java index a56e1e1..c4c9d99 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java @@ -21,6 +21,7 @@ package org.apache.bval.jsr; import javax.validation.ConstraintTarget; import javax.validation.Payload; import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ValidateUnwrappedValue; import java.io.Serializable; import java.lang.annotation.Annotation; @@ -220,4 +221,16 @@ public class ConstraintDescriptorImpl<T extends Annotation> implements Constrain result = 31 * result + (template != null ? template.hashCode() : 0); return result; } + + @Override + public ValidateUnwrappedValue getValueUnwrapping() { + // TODO Auto-generated method stub + return null; + } + + @Override + public <U> U unwrap(Class<U> arg0) { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java index 5b51141..5ba14ca 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java @@ -39,6 +39,8 @@ import javax.validation.ValidationException; import javax.validation.constraintvalidation.SupportedValidationTarget; import javax.validation.constraintvalidation.ValidationTarget; import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ValidateUnwrappedValue; + import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Array; @@ -54,6 +56,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * Description: Adapter between Constraint (JSR303) and Validation (Core)<br/> @@ -328,10 +331,12 @@ public class ConstraintValidation<T extends Annotation> implements Validation, C throw new UnexpectedTypeException(message); } if (types.size() > 1) { - throw new UnexpectedTypeException( - String.format("Ambiguous validators for type %s. See: @%s at %s. Validators are: %s", - stringForType(targetType), anno.annotationType().getSimpleName(), stringForLocation(owner, access), - StringUtils.join(types, ", "))); + throw new UnexpectedTypeException(String.format( + "Ambiguous validators for type %s. See: @%s at %s. Validators are: %s", + stringForType(targetType), + anno.annotationType().getSimpleName(), + stringForLocation(owner, access), types.stream() + .map(Object::toString).collect(Collectors.joining(", ")))); } } @@ -524,9 +529,13 @@ public class ConstraintValidation<T extends Annotation> implements Validation, C * {@inheritDoc} */ @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) public Set<ConstraintDescriptor<?>> getComposingConstraints() { - return composedConstraints == null ? Collections.EMPTY_SET : composedConstraints; + if (composedConstraints == null) { + return Collections.emptySet(); + } + final Set result = composedConstraints; + return result; } /** @@ -581,4 +590,16 @@ public class ConstraintValidation<T extends Annotation> implements Validation, C public void setValidated(final boolean validated) { this.validated = validated; } + + @Override + public ValidateUnwrappedValue getValueUnwrapping() { + // TODO Auto-generated method stub + return null; + } + + @Override + public <U> U unwrap(Class<U> arg0) { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java index 3599603..930170d 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java @@ -25,6 +25,7 @@ import org.apache.bval.jsr.util.NodeImpl; import org.apache.bval.jsr.util.PathImpl; import org.apache.bval.model.ValidationListener; +import javax.validation.ClockProvider; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.Path; @@ -38,7 +39,10 @@ import java.util.List; * Description: Short-lived {@link ConstraintValidatorContext} implementation passed by * a {@link ConstraintValidation} to its adapted {@link ConstraintValidator}. <br/> */ -public class ConstraintValidatorContextImpl implements ConstraintValidatorContext { +@Deprecated +public class ConstraintValidatorContextImpl + extends org.apache.bval.jsr.job.ConstraintValidatorContextImpl<Object> + implements ConstraintValidatorContext { private final List<ValidationListener.Error> errorMessages = new LinkedList<ValidationListener.Error>(); private final ConstraintValidation<?> constraintDescriptor; @@ -53,6 +57,7 @@ public class ConstraintValidatorContextImpl implements ConstraintValidatorContex */ public ConstraintValidatorContextImpl(GroupValidationContext<?> validationContext, ConstraintValidation<?> aConstraintValidation) { + super(); this.validationContext = validationContext; this.constraintDescriptor = aConstraintValidation; } @@ -154,6 +159,13 @@ public class ConstraintValidatorContextImpl implements ConstraintValidatorContex parent.addError(messageTemplate, propertyPath); return parent; } + + @Override + public ContainerElementNodeBuilderCustomizableContext addContainerElementNode( + String arg0, Class<?> arg1, Integer arg2) { + // TODO Auto-generated method stub + return null; + } } /** @@ -190,4 +202,10 @@ public class ConstraintValidatorContextImpl implements ConstraintValidatorContex public void addError(String messageTemplate, Path propertyPath) { errorMessages.add(new ValidationListener.Error(messageTemplate, propertyPath, null)); } + + @Override + public ClockProvider getClockProvider() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java index 1092323..572c39a 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java @@ -19,6 +19,8 @@ package org.apache.bval.jsr; +import java.util.Objects; + import javax.validation.ConstraintValidator; import javax.validation.Path; @@ -120,12 +122,7 @@ final class ConstraintValidatorIdentity { */ @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.bean == null) ? 0 : this.bean.hashCode()); - result = prime * result + ((this.path == null) ? 0 : this.path.hashCode()); - result = prime * result + ((this.constraintValidator == null) ? 0 : this.constraintValidator.hashCode()); - return result; + return Objects.hash(bean, path, constraintValidator); } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java index c367b8e..91ae20d 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java @@ -20,15 +20,20 @@ import javax.validation.ConstraintViolation; import javax.validation.Path; import javax.validation.ValidationException; import javax.validation.metadata.ConstraintDescriptor; + +import org.apache.bval.util.Exceptions; + import java.io.Serializable; import java.lang.annotation.ElementType; import java.util.Arrays; +import java.util.Objects; /** * Description: Describe a constraint validation defect.<br/> - * From rootBean and propertyPath, it is possible to rebuild the context of the failure + * From rootBean and propertyPath, it is possible to rebuild the context of the + * failure */ -class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable { +public class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable { /** Serialization version */ private static final long serialVersionUID = 1L; @@ -49,8 +54,11 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable /** * Create a new ConstraintViolationImpl instance. - * @param messageTemplate - message reason (raw message) - * @param message - interpolated message (locale specific) + * + * @param messageTemplate + * - message reason (raw message) + * @param message + * - interpolated message (locale specific) * @param rootBean * @param leafBean * @param propertyPath @@ -79,8 +87,8 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable } /** - * {@inheritDoc} - * former name getInterpolatedMessage() + * {@inheritDoc} former name getInterpolatedMessage() + * * @return The interpolated error message for this constraint violation. */ @Override @@ -98,6 +106,7 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable /** * {@inheritDoc} + * * @return Root bean being validated */ @Override @@ -133,6 +142,7 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable /** * {@inheritDoc} + * * @return The value failing to pass the constraint */ @Override @@ -142,8 +152,9 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable /** * {@inheritDoc} - * @return the property path to the value from <code>rootBean</code> - * Null if the value is the rootBean itself + * + * @return the property path to the value from <code>rootBean</code> Null if + * the value is the rootBean itself */ @Override public Path getPropertyPath() { @@ -160,10 +171,8 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable @Override public <U> U unwrap(Class<U> type) { - if (type.isInstance(this)) { - return type.cast(this); - } - throw new ValidationException("Type " + type + " is not supported"); + Exceptions.raiseUnless(type.isInstance(this), ValidationException::new, "Type %s is not supported", type); + return type.cast(this); } /** @@ -171,45 +180,28 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable */ @Override public String toString() { - return "ConstraintViolationImpl{" + "rootBean=" + rootBean + ", propertyPath='" + propertyPath + '\'' - + ", message='" + message + '\'' + ", leafBean=" + leafBean + ", value=" + value + '}'; + return String.format("%s{rootBean=%s, propertyPath='%s', message='%s', leafBean=%s, value=%s}", + ConstraintViolationImpl.class.getSimpleName(), rootBean, propertyPath, message, leafBean, value); } @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || !getClass().equals(o.getClass())) { return false; + } - ConstraintViolationImpl that = (ConstraintViolationImpl) o; - - if (constraintDescriptor != null ? !constraintDescriptor.equals(that.constraintDescriptor) - : that.constraintDescriptor != null) - return false; - if (elementType != that.elementType) - return false; - if (leafBean != null ? !leafBean.equals(that.leafBean) : that.leafBean != null) - return false; - if (message != null ? !message.equals(that.message) : that.message != null) - return false; - if (messageTemplate != null ? !messageTemplate.equals(that.messageTemplate) : that.messageTemplate != null) - return false; - // Probably incorrect - comparing Object[] arrays with Arrays.equals - if (!Arrays.equals(parameters, that.parameters)) - return false; - if (propertyPath != null ? !propertyPath.equals(that.propertyPath) : that.propertyPath != null) - return false; - if (returnValue != null ? !returnValue.equals(that.returnValue) : that.returnValue != null) - return false; - if (rootBean != null ? !rootBean.equals(that.rootBean) : that.rootBean != null) - return false; - if (rootBeanClass != null ? !rootBeanClass.equals(that.rootBeanClass) : that.rootBeanClass != null) - return false; - if (value != null ? !value.equals(that.value) : that.value != null) - return false; + @SuppressWarnings("rawtypes") + final ConstraintViolationImpl that = (ConstraintViolationImpl) o; - return true; + return Objects.equals(constraintDescriptor, that.constraintDescriptor) && elementType == that.elementType + && Objects.equals(leafBean, that.leafBean) && Objects.equals(message, that.message) + && Objects.equals(messageTemplate, that.messageTemplate) && Arrays.equals(parameters, that.parameters) + && Objects.equals(propertyPath, that.propertyPath) && Objects.equals(returnValue, that.returnValue) + && Objects.equals(rootBean, that.rootBean) && Objects.equals(rootBeanClass, that.rootBeanClass) + && Objects.equals(value, that.value); } @Override @@ -217,18 +209,10 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable return hashCode; } - public int computeHashCode() { - int result = messageTemplate != null ? messageTemplate.hashCode() : 0; - result = 31 * result + (message != null ? message.hashCode() : 0); - result = 31 * result + (rootBean != null ? rootBean.hashCode() : 0); - result = 31 * result + (rootBeanClass != null ? rootBeanClass.hashCode() : 0); - result = 31 * result + (leafBean != null ? leafBean.hashCode() : 0); - result = 31 * result + (value != null ? value.hashCode() : 0); - result = 31 * result + (propertyPath != null ? propertyPath.hashCode() : 0); - result = 31 * result + (elementType != null ? elementType.hashCode() : 0); - result = 31 * result + (constraintDescriptor != null ? constraintDescriptor.hashCode() : 0); - result = 31 * result + (returnValue != null ? returnValue.hashCode() : 0); - result = 31 * result + (parameters != null ? Arrays.hashCode(parameters) : 0); + private int computeHashCode() { + int result = Objects.hash(messageTemplate, message, rootBean, rootBeanClass, leafBean, value, propertyPath, + elementType, constraintDescriptor, returnValue); + result = 31 * result + (parameters == null ? 0 : Arrays.hashCode(parameters)); return result; } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java index 4aca48a..9474705 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java @@ -32,8 +32,7 @@ import java.util.concurrent.CopyOnWriteArrayList; * Description: create constraint instances with the default / no-arg constructor <br/> */ public class DefaultConstraintValidatorFactory implements ConstraintValidatorFactory, Closeable { - private final Collection<BValExtension.Releasable<?>> releasables = - new CopyOnWriteArrayList<BValExtension.Releasable<?>>(); + private final Collection<BValExtension.Releasable<?>> releasables = new CopyOnWriteArrayList<>(); private volatile Boolean useCdi = null; // store it to avoid NoClassDefFoundError when cdi is not present (it is slow) + lazily (to wait cdi is started) /** @@ -49,9 +48,7 @@ public class DefaultConstraintValidatorFactory implements ConstraintValidatorFac if (useCdi == null) { try { useCdi = BValExtension.getBeanManager() != null; - } catch (final NoClassDefFoundError error) { - useCdi = Boolean.FALSE; - } catch (final Exception e) { + } catch (NoClassDefFoundError | Exception error) { useCdi = Boolean.FALSE; } } @@ -69,10 +66,7 @@ public class DefaultConstraintValidatorFactory implements ConstraintValidatorFac return instance.getInstance(); } throw new IllegalStateException("Can't create " + constraintClass.getName()); - } catch (final Exception e) { - return constraintClass.newInstance(); - } catch (final NoClassDefFoundError error) { - return constraintClass.newInstance(); + } catch (Exception | NoClassDefFoundError e) { } } return constraintClass.newInstance(); http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java index 8c77162..6a85a2a 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java @@ -54,10 +54,10 @@ public class DefaultMessageInterpolator implements MessageInterpolator { private Locale defaultLocale; /** User specified resource bundles hashed against their locale. */ - private final Map<Locale, ResourceBundle> userBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>(); + private final Map<Locale, ResourceBundle> userBundlesMap = new ConcurrentHashMap<>(); /** Builtin resource bundles hashed against their locale. */ - private final Map<Locale, ResourceBundle> defaultBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>(); + private final Map<Locale, ResourceBundle> defaultBundlesMap = new ConcurrentHashMap<>(); private final MessageEvaluator evaluator; @@ -83,12 +83,12 @@ public class DefaultMessageInterpolator implements MessageInterpolator { userBundlesMap.put(defaultLocale, resourceBundle); } - MessageEvaluator ev = null; + MessageEvaluator ev; try { ev = MessageEvaluator.class .cast(getClass().getClassLoader().loadClass("org.apache.bval.el.ELFacade").newInstance()); } catch (final Throwable e) { // can be exception or error - // no-op + ev = null; } evaluator = ev; } @@ -170,47 +170,42 @@ public class DefaultMessageInterpolator implements MessageInterpolator { * @return the resource bundle or <code>null</code> if none is found. */ private ResourceBundle getFileBasedResourceBundle(Locale locale) { - ResourceBundle rb = null; + ResourceBundle rb; final ClassLoader classLoader = Reflection.getClassLoader(DefaultMessageInterpolator.class); if (classLoader != null) { rb = loadBundle(classLoader, locale, USER_VALIDATION_MESSAGES + " not found by thread local classloader"); - } - + } else { // 2011-03-27 jw: No privileged action required. // A class can always access the classloader of itself and of subclasses. - if (rb == null) { rb = loadBundle(getClass().getClassLoader(), locale, USER_VALIDATION_MESSAGES + " not found by validator classloader"); } if (LOG_FINEST) { - if (rb != null) { - log.log(Level.FINEST, String.format("%s found", USER_VALIDATION_MESSAGES)); - } else { + if (rb == null) { log.log(Level.FINEST, String.format("%s not found. Delegating to %s", USER_VALIDATION_MESSAGES, DEFAULT_VALIDATION_MESSAGES)); + } else { + log.log(Level.FINEST, String.format("%s found", USER_VALIDATION_MESSAGES)); } } return rb; } private ResourceBundle loadBundle(ClassLoader classLoader, Locale locale, String message) { - ResourceBundle rb = null; try { - rb = ResourceBundle.getBundle(USER_VALIDATION_MESSAGES, locale, classLoader); + return ResourceBundle.getBundle(USER_VALIDATION_MESSAGES, locale, classLoader); } catch (final MissingResourceException e) { log.fine(message); } - return rb; + return null; } private String replaceVariables(String message, ResourceBundle bundle, Locale locale, boolean recurse) { final Matcher matcher = messageParameterPattern.matcher(message); final StringBuffer sb = new StringBuffer(64); - String resolvedParameterValue; while (matcher.find()) { final String parameter = matcher.group(1); - resolvedParameterValue = resolveParameter(parameter, bundle, locale, recurse); - + String resolvedParameterValue = resolveParameter(parameter, bundle, locale, recurse); matcher.appendReplacement(sb, sanitizeForAppendReplacement(resolvedParameterValue)); } matcher.appendTail(sb); @@ -242,13 +237,13 @@ public class DefaultMessageInterpolator implements MessageInterpolator { private String resolveParameter(String parameterName, ResourceBundle bundle, Locale locale, boolean recurse) { String parameterValue; try { - if (bundle != null) { + if (bundle == null) { + parameterValue = parameterName; + } else { parameterValue = bundle.getString(removeCurlyBrace(parameterName)); if (recurse) { parameterValue = replaceVariables(parameterValue, bundle, locale, recurse); } - } else { - parameterValue = parameterName; } } catch (final MissingResourceException e) { // return parameter itself http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java index 671b0d9..e63bdf4 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java @@ -38,6 +38,11 @@ public class DefaultValidationProviderResolver implements ValidationProviderReso //TODO - Spec recommends caching per classloader private static final String SPI_CFG = "META-INF/services/javax.validation.spi.ValidationProvider"; + private static ClassLoader getCurrentClassLoader() { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + return cl == null ? DefaultValidationProviderResolver.class.getClassLoader() : cl; + } + /** * {@inheritDoc} */ @@ -46,43 +51,28 @@ public class DefaultValidationProviderResolver implements ValidationProviderReso List<ValidationProvider<?>> providers = new ArrayList<ValidationProvider<?>>(); try { // get our classloader - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl == null) - cl = DefaultValidationProviderResolver.class.getClassLoader(); + ClassLoader cl = getCurrentClassLoader(); // find all service provider cfgs Enumeration<URL> cfgs = cl.getResources(SPI_CFG); while (cfgs.hasMoreElements()) { final URL url = cfgs.nextElement(); - BufferedReader br = null; - try { - br = new BufferedReader(new InputStreamReader(url.openStream()), 256); - String line = br.readLine(); - // cfgs may contain multiple providers and/or comments - while (line != null) { - line = line.trim(); - if (!line.startsWith("#")) { - try { - // try loading the specified class - @SuppressWarnings("rawtypes") - final Class<? extends ValidationProvider> providerType = - cl.loadClass(line).asSubclass(ValidationProvider.class); - // create an instance to return - providers - .add(Reflection.newInstance(providerType.asSubclass(ValidationProvider.class))); - - } catch (ClassNotFoundException e) { - throw new ValidationException( - "Failed to load provider " + line + " configured in file " + url, e); - } + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()), 256)) { + br.lines().filter(s -> s.charAt(0) != '#').map(String::trim).forEach(line -> { + // cfgs may contain multiple providers and/or comments + try { + // try loading the specified class + @SuppressWarnings("rawtypes") + final Class<? extends ValidationProvider> providerType = + cl.loadClass(line).asSubclass(ValidationProvider.class); + // create an instance to return + providers.add(Reflection.newInstance(providerType)); + } catch (ClassNotFoundException e) { + throw new ValidationException( + "Failed to load provider " + line + " configured in file " + url, e); } - line = br.readLine(); - } + }); } catch (IOException e) { throw new ValidationException("Error trying to read " + url, e); - } finally { - if (br != null) { - br.close(); - } } } } catch (IOException e) { http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java b/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java index 3ec666e..26391e6 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java @@ -18,6 +18,8 @@ */ package org.apache.bval.jsr; +import java.util.Objects; + /** * Class that stores the needed properties to avoid circular paths when * validating an object graph. @@ -80,32 +82,16 @@ public class GraphBeanIdentity { */ @Override public boolean equals(Object obj) { - if (this == obj) { return true; } - - if (obj == null) { - return false; - } - if (!(obj instanceof GraphBeanIdentity)) { return false; } - GraphBeanIdentity other = (GraphBeanIdentity) obj; - // Bean ref must be the same - if (this.bean != other.bean) { - return false; - } - - // Group ref must be the same - if (this.group != other.group) { - return false; - } - - return true; + // Bean ref must be the same; Group ref must be the same + return bean == other.bean && group == other.group; } /** @@ -113,11 +99,7 @@ public class GraphBeanIdentity { */ @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.bean == null) ? 0 : this.bean.hashCode()); - result = prime * result + ((this.group == null) ? 0 : this.group.hashCode()); - return result; + return Objects.hash(bean, group); } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java index 187fd7e..65f3ecc 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java @@ -21,6 +21,7 @@ import org.apache.bval.jsr.groups.GroupConversionDescriptorImpl; import org.apache.bval.model.MetaBean; import org.apache.bval.model.Validation; +import javax.validation.metadata.ContainerElementTypeDescriptor; import javax.validation.metadata.GroupConversionDescriptor; import javax.validation.metadata.ParameterDescriptor; import java.util.Set; @@ -86,4 +87,10 @@ public class ParameterDescriptorImpl extends ElementDescriptorImpl implements Pa groupConversions.add(new GroupConversionDescriptorImpl(from, to)); super.addGroupMapping(from, to); } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java index 7f7c56d..03cf5de 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java @@ -21,6 +21,9 @@ package org.apache.bval.jsr; import org.apache.bval.model.Features; import org.apache.bval.model.MetaProperty; +import java.util.Set; + +import javax.validation.metadata.ContainerElementTypeDescriptor; import javax.validation.metadata.PropertyDescriptor; /** @@ -67,4 +70,10 @@ class PropertyDescriptorImpl extends ElementDescriptorImpl implements PropertyDe return "PropertyDescriptorImpl{" + "returnType=" + elementClass + ", propertyPath='" + propertyPath + '\'' + '}'; } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java index b1fc72d..a6faa9b 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java @@ -18,8 +18,10 @@ package org.apache.bval.jsr; import org.apache.bval.model.MetaBean; +import javax.validation.metadata.ContainerElementTypeDescriptor; import javax.validation.metadata.ReturnValueDescriptor; import java.util.Collection; +import java.util.Set; public class ReturnValueDescriptorImpl extends ElementDescriptorImpl implements ReturnValueDescriptor { public ReturnValueDescriptorImpl(final MetaBean metaBean, Class<?> returnType, @@ -32,4 +34,10 @@ public class ReturnValueDescriptorImpl extends ElementDescriptorImpl implements public boolean hasConstraints() { return false; } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java index 4f9d10a..6a211ed 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java @@ -18,6 +18,8 @@ */ package org.apache.bval.jsr.groups; +import java.util.Objects; + import javax.validation.groups.Default; /** @@ -52,7 +54,7 @@ public final class Group { */ @Override public String toString() { - return "Group{" + "group=" + group + '}'; + return String.format("%s{group=%s}", Group.class.getSimpleName(), group); } /** @@ -71,13 +73,10 @@ public final class Group { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if (o == null || !getClass().equals(o.getClass())) { return false; } - - Group group1 = (Group) o; - - return group != null ? group.equals(group1.group) : group1.group == null; + return Objects.equals(group, ((Group) o).group); } /** @@ -85,6 +84,6 @@ public final class Group { */ @Override public int hashCode() { - return (group != null ? group.hashCode() : 0); + return Objects.hashCode(group); } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java index ba3a617..6d45ced 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java @@ -26,10 +26,9 @@ public class GroupConversionDescriptorImpl implements GroupConversionDescriptor public GroupConversionDescriptorImpl(final Group from, final Group to) { this.from = from.getGroup(); - if (this.from.getAnnotation(GroupSequence.class) != null) { + if (this.from.isAnnotationPresent(GroupSequence.class)) { throw new ConstraintDeclarationException("from() can't get a group sequence"); } - this.to = to.getGroup(); } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java index 162bb66..3e7f008 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java @@ -18,25 +18,29 @@ */ package org.apache.bval.jsr.groups; -import javax.validation.GroupDefinitionException; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; +import javax.validation.GroupDefinitionException; + +import org.apache.bval.util.Exceptions; + /** - * Defines the order to validate groups during validation. - * with some inspiration from reference implementation + * Defines the order to validate groups during validation. with some inspiration + * from reference implementation * * @author Roman Stumm */ public class Groups { - /** The list of single groups. */ - final List<Group> groups = new LinkedList<Group>(); - /** The list of sequences. */ - final List<List<Group>> sequences = new LinkedList<List<Group>>(); + private final List<List<Group>> sequences = new ArrayList<>(); + + /** The list of single groups. */ + final List<Group> groups = new ArrayList<>(); /** * Get the Groups. + * * @return {@link List} of {@link Group}. */ public List<Group> getGroups() { @@ -45,6 +49,7 @@ public class Groups { /** * Get the Group sequences. + * * @return {@link List} of {@link List} of {@link Group} */ public List<List<Group>> getSequences() { @@ -53,7 +58,9 @@ public class Groups { /** * Insert a {@link Group}. - * @param group to insert + * + * @param group + * to insert */ void insertGroup(Group group) { if (!groups.contains(group)) { @@ -63,52 +70,52 @@ public class Groups { /** * Insert a sequence. - * @param groups {@link List} of {@link Group} to insert + * + * @param groups + * {@link List} of {@link Group} to insert */ void insertSequence(List<Group> groups) { - if (groups == null || groups.isEmpty()) { - return; - } - - if (!sequences.contains(groups)) { + if (!(groups == null || groups.isEmpty() || sequences.contains(groups))) { sequences.add(groups); } } /** - * Assert that the default group can be expanded to <code>defaultGroups</code>. + * Assert that the default group can be expanded to + * <code>defaultGroups</code>. + * * @param defaultGroups */ public void assertDefaultGroupSequenceIsExpandable(List<Group> defaultGroups) { for (List<Group> groupList : sequences) { - int idx = groupList.indexOf(Group.DEFAULT); - if (idx != -1) { + final int idx = groupList.indexOf(Group.DEFAULT); + if (idx >= 0) { ensureExpandable(groupList, defaultGroups, idx); } } } private void ensureExpandable(List<Group> groupList, List<Group> defaultGroupList, int defaultGroupIndex) { - for (int i = 0; i < defaultGroupList.size(); i++) { - Group group = defaultGroupList.get(i); + for (int i = 0, sz = defaultGroupList.size(); i < sz; i++) { + final Group group = defaultGroupList.get(i); if (group.isDefault()) { continue; // the default group is the one we want to replace } - int index = groupList.indexOf(group); // sequence contains group of default group sequence - if (index == -1) { - continue; // if group is not in the sequence + // sequence contains group of default group sequence + final int index = groupList.indexOf(group); + if (index < 0) { + // group is not in the sequence + continue; } - if ((i == 0 && index == defaultGroupIndex - 1) || (i == defaultGroupList.size() - 1 && index == defaultGroupIndex + 1)) { - // if we are at the beginning or end of he defaultGroupSequence and the - // matches are either directly before or after we can continue, - // since we basically have two groups + // if we are at the beginning or end of he defaultGroupSequence + // and the matches are either directly before or after we can + // continue, since we basically have two groups continue; } - throw new GroupDefinitionException( - "Unable to expand default group list" + defaultGroupList + " into sequence " + groupList); + Exceptions.raise(GroupDefinitionException::new, "Unable to expand default group list %s into sequence %s", + defaultGroupList, groupList); } } - } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java index 398d6c3..ae6f629 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java @@ -18,126 +18,115 @@ */ package org.apache.bval.jsr.groups; -import javax.validation.GroupDefinitionException; -import javax.validation.GroupSequence; -import javax.validation.ValidationException; -import javax.validation.groups.Default; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import javax.validation.GroupDefinitionException; +import javax.validation.GroupSequence; +import javax.validation.ValidationException; +import javax.validation.groups.Default; + +import org.apache.bval.util.Exceptions; +import org.apache.bval.util.Validate; + /** * Description: compute group order, based on the RI behavior as to guarantee * compatibility with interpretations of the spec.<br/> * Implementation is thread-safe. */ public class GroupsComputer { - public static final Class<?>[] DEFAULT_GROUP = new Class<?>[] { Default.class }; + public static final Class<?>[] DEFAULT_GROUP = { Default.class }; - /** The default group array used in case any of the validate methods is called without a group. */ + /** + * The default group array used in case any of the validate methods is + * called without a group. + */ private static final Groups DEFAULT_GROUPS; static { - DEFAULT_GROUPS = new GroupsComputer().computeGroups(Arrays.asList(DEFAULT_GROUP)); + DEFAULT_GROUPS = new Groups(); + for (Class<?> g : DEFAULT_GROUP) { + DEFAULT_GROUPS.insertGroup(new Group(g)); + } } /** caching resolved groups in a thread-safe map. */ - private final Map<Class<?>, List<Group>> resolvedSequences = new ConcurrentHashMap<Class<?>, List<Group>>(); + private final Map<Class<?>, List<Group>> resolvedSequences = new ConcurrentHashMap<>(); /** * Compute groups from an array of group classes. + * * @param groups * @return {@link Groups} */ - public Groups computeGroups(Class<?>[] groups) { - if (groups == null) { - throw new IllegalArgumentException("null passed as group"); - } - - // if no groups is specified use the default - if (groups.length == 0) { - return DEFAULT_GROUPS; - } - + @SafeVarargs + public final Groups computeGroups(Class<?>... groups) { + Exceptions.raiseIf(groups == null, IllegalArgumentException::new, "null validation groups specified"); return computeGroups(Arrays.asList(groups)); } /** * Main compute implementation. + * * @param groups * @return {@link Groups} */ protected Groups computeGroups(Collection<Class<?>> groups) { - if (groups == null || groups.size() == 0) { - throw new IllegalArgumentException("At least one group has to be specified."); + Validate.notNull(groups, "groups"); + + if (groups.isEmpty() || Arrays.asList(DEFAULT_GROUP).equals(new ArrayList<>(groups))) { + return DEFAULT_GROUPS; } + Exceptions.raiseIf(groups.stream().anyMatch(Objects::isNull), IllegalArgumentException::new, + "Null group specified"); for (final Class<?> clazz : groups) { - if (clazz == null) { - throw new IllegalArgumentException("At least one group has to be specified."); - } - - if (!clazz.isInterface()) { - throw new ValidationException("A group has to be an interface. " + clazz.getName() + " is not."); - } + Exceptions.raiseUnless(clazz.isInterface(), ValidationException::new, + "A group must be an interface. %s is not.", clazz); } - - Groups chain = new Groups(); + final Groups chain = new Groups(); for (Class<?> clazz : groups) { - GroupSequence anno = clazz.getAnnotation(GroupSequence.class); + final GroupSequence anno = clazz.getAnnotation(GroupSequence.class); if (anno == null) { - Group group = new Group(clazz); - chain.insertGroup(group); + chain.insertGroup(new Group(clazz)); insertInheritedGroups(clazz, chain); - } else { - insertSequence(clazz, anno, chain); + continue; } + chain.insertSequence( + resolvedSequences.computeIfAbsent(clazz, g -> resolveSequence(g, anno, new HashSet<>()))); } - return chain; } private void insertInheritedGroups(Class<?> clazz, Groups chain) { for (Class<?> extendedInterface : clazz.getInterfaces()) { - Group group = new Group(extendedInterface); - chain.insertGroup(group); + chain.insertGroup(new Group(extendedInterface)); insertInheritedGroups(extendedInterface, chain); } } - private void insertSequence(Class<?> clazz, GroupSequence anno, Groups chain) { - List<Group> sequence; - if (resolvedSequences.containsKey(clazz)) { - sequence = resolvedSequences.get(clazz); - } else { - sequence = resolveSequence(clazz, anno, new HashSet<Class<?>>()); - } - chain.insertSequence(sequence); - } - private List<Group> resolveSequence(Class<?> group, GroupSequence sequenceAnnotation, Set<Class<?>> processedSequences) { - if (processedSequences.contains(group)) { - throw new GroupDefinitionException("Cyclic dependency in groups definition"); - } else { - processedSequences.add(group); - } - List<Group> resolvedGroupSequence = new LinkedList<Group>(); - Class<?>[] sequenceArray = sequenceAnnotation.value(); - for (Class<?> clazz : sequenceArray) { - GroupSequence anno = clazz.getAnnotation(GroupSequence.class); + Exceptions.raiseUnless(processedSequences.add(group), GroupDefinitionException::new, + "Cyclic dependency in groups definition"); + + final List<Group> resolvedGroupSequence = new ArrayList<>(); + for (Class<?> clazz : sequenceAnnotation.value()) { + final GroupSequence anno = clazz.getAnnotation(GroupSequence.class); if (anno == null) { - resolvedGroupSequence.add(new Group(clazz)); // group part of sequence + // group part of sequence + resolvedGroupSequence.add(new Group(clazz)); } else { - List<Group> tmpSequence = resolveSequence(clazz, anno, processedSequences); // recursion! - resolvedGroupSequence.addAll(tmpSequence); + // recursion! + resolvedGroupSequence.addAll(resolveSequence(clazz, anno, processedSequences)); } } - resolvedSequences.put(group, resolvedGroupSequence); return resolvedGroupSequence; } } http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java b/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java index 2b43bcd..dec9ae8 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java @@ -18,30 +18,29 @@ */ package org.apache.bval.jsr.parameter; -import javax.validation.ParameterNameProvider; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.Method; -import java.util.ArrayList; +import java.lang.reflect.Parameter; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.validation.ParameterNameProvider; public class DefaultParameterNameProvider implements ParameterNameProvider { - private static final String ARG = "arg"; + + private static List<String> parameterNames(Executable exe) { + return Stream.of(exe.getParameters()).map(Parameter::getName).collect(Collectors.toList()); + } @Override public List<String> getParameterNames(Constructor<?> constructor) { - return names(constructor.getParameterTypes().length); + return parameterNames(constructor); } @Override public List<String> getParameterNames(Method method) { - return names(method.getParameterTypes().length); - } - - private static List<String> names(final int length) { - final List<String> list = new ArrayList<String>(); - for (int i = 0; i < length; i++) { - list.add(ARG + i); - } - return list; + return parameterNames(method); } }
