/*
 * Hibernate Validator, declare and validate application constraints
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
 */
package org.hibernate.validator.internal.metadata.core;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Member;
import java.util.Map;

import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;

import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap;

An AnnotationProcessingOptions instance keeps track of annotations which should be ignored as configuration source. The main validation source for Bean Validation is annotation and alternate configuration sources use this class to override/ignore existing annotations.
Author:Hardy Ferentschik
/** * An {@code AnnotationProcessingOptions} instance keeps track of annotations which should be ignored as configuration source. * The main validation source for Bean Validation is annotation and alternate configuration sources use this class * to override/ignore existing annotations. * * @author Hardy Ferentschik */
public class AnnotationProcessingOptionsImpl implements AnnotationProcessingOptions { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
Keeps track whether the 'ignore-annotations' flag is set on bean level in the xml configuration. If 'ignore-annotations' is not specified true is the default.
/** * Keeps track whether the 'ignore-annotations' flag is set on bean level in the xml configuration. If 'ignore-annotations' * is not specified {@code true} is the default. */
private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = newHashMap();
Keeps track of explicitly excluded class level constraints.
/** * Keeps track of explicitly excluded class level constraints. */
private final Map<Class<?>, Boolean> annotationIgnoresForClasses = newHashMap();
Keeps track of explicitly excluded members (fields and properties).
/** * Keeps track of explicitly excluded members (fields and properties). */
private final Map<Member, Boolean> annotationIgnoredForMembers = newHashMap();
Keeps track of explicitly excluded return value constraints for methods/constructors.
/** * Keeps track of explicitly excluded return value constraints for methods/constructors. */
private final Map<Member, Boolean> annotationIgnoresForReturnValues = newHashMap();
Keeps track of explicitly excluded cross parameter constraints for methods/constructors.
/** * Keeps track of explicitly excluded cross parameter constraints for methods/constructors. */
private final Map<Member, Boolean> annotationIgnoresForCrossParameter = newHashMap();
Keeps track whether the 'ignore-annotations' flag is set on a method/constructor parameter
/** * Keeps track whether the 'ignore-annotations' flag is set on a method/constructor parameter */
private final Map<ExecutableParameterKey, Boolean> annotationIgnoresForMethodParameter = newHashMap(); @Override public boolean areMemberConstraintsIgnoredFor(Member member) { Class<?> clazz = member.getDeclaringClass(); if ( annotationIgnoredForMembers.containsKey( member ) ) { return annotationIgnoredForMembers.get( member ); } else { return areAllConstraintAnnotationsIgnoredFor( clazz ); } } @Override public boolean areReturnValueConstraintsIgnoredFor(Member member) { if ( annotationIgnoresForReturnValues.containsKey( member ) ) { return annotationIgnoresForReturnValues.get( member ); } else { return areMemberConstraintsIgnoredFor( member ); } } @Override public boolean areCrossParameterConstraintsIgnoredFor(Member member) { if ( annotationIgnoresForCrossParameter.containsKey( member ) ) { return annotationIgnoresForCrossParameter.get( member ); } else { return areMemberConstraintsIgnoredFor( member ); } } @Override public boolean areParameterConstraintsIgnoredFor(Member member, int index) { ExecutableParameterKey key = new ExecutableParameterKey( member, index ); if ( annotationIgnoresForMethodParameter.containsKey( key ) ) { return annotationIgnoresForMethodParameter.get( key ); } else { return areMemberConstraintsIgnoredFor( member ); } } @Override public boolean areClassLevelConstraintsIgnoredFor(Class<?> clazz) { boolean ignoreAnnotation; if ( annotationIgnoresForClasses.containsKey( clazz ) ) { ignoreAnnotation = annotationIgnoresForClasses.get( clazz ); } else { ignoreAnnotation = areAllConstraintAnnotationsIgnoredFor( clazz ); } if ( LOG.isDebugEnabled() && ignoreAnnotation ) { LOG.debugf( "Class level annotation are getting ignored for %s.", clazz.getName() ); } return ignoreAnnotation; } @Override public void merge(AnnotationProcessingOptions annotationProcessingOptions) { AnnotationProcessingOptionsImpl annotationProcessingOptionsImpl = (AnnotationProcessingOptionsImpl) annotationProcessingOptions; // TODO rethink the "merging" of these options. It will depend on the order of merging (HF) this.ignoreAnnotationDefaults.putAll( annotationProcessingOptionsImpl.ignoreAnnotationDefaults ); this.annotationIgnoresForClasses.putAll( annotationProcessingOptionsImpl.annotationIgnoresForClasses ); this.annotationIgnoredForMembers.putAll( annotationProcessingOptionsImpl.annotationIgnoredForMembers ); this.annotationIgnoresForReturnValues .putAll( annotationProcessingOptionsImpl.annotationIgnoresForReturnValues ); this.annotationIgnoresForCrossParameter .putAll( annotationProcessingOptionsImpl.annotationIgnoresForCrossParameter ); this.annotationIgnoresForMethodParameter.putAll( annotationProcessingOptionsImpl.annotationIgnoresForMethodParameter ); } public void ignoreAnnotationConstraintForClass(Class<?> clazz, Boolean b) { if ( b == null ) { ignoreAnnotationDefaults.put( clazz, Boolean.TRUE ); } else { ignoreAnnotationDefaults.put( clazz, b ); } } public void ignoreConstraintAnnotationsOnMember(Member member, Boolean b) { annotationIgnoredForMembers.put( member, b ); } public void ignoreConstraintAnnotationsForReturnValue(Member member, Boolean b) { annotationIgnoresForReturnValues.put( member, b ); } public void ignoreConstraintAnnotationsForCrossParameterConstraint(Member member, Boolean b) { annotationIgnoresForCrossParameter.put( member, b ); } public void ignoreConstraintAnnotationsOnParameter(Member member, int index, Boolean b) { ExecutableParameterKey key = new ExecutableParameterKey( member, index ); annotationIgnoresForMethodParameter.put( key, b ); } public void ignoreClassLevelConstraintAnnotations(Class<?> clazz, boolean b) { annotationIgnoresForClasses.put( clazz, b ); } private boolean areAllConstraintAnnotationsIgnoredFor(Class<?> clazz) { return ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz ); } public class ExecutableParameterKey { private final Member member; private final int index; public ExecutableParameterKey(Member member, int index) { this.member = member; this.index = index; } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } ExecutableParameterKey that = (ExecutableParameterKey) o; if ( index != that.index ) { return false; } if ( member != null ? !member.equals( that.member ) : that.member != null ) { return false; } return true; } @Override public int hashCode() { int result = member != null ? member.hashCode() : 0; result = 31 * result + index; return result; } } }