Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hibernate.validator.internal.xml.mapping.BeanStaxBuilder Maven / Gradle / Ivy
Go to download
Hibernate's Bean Validation (JSR-380) reference implementation.
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or .
*/
package org.hibernate.validator.internal.xml.mapping;
import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.hibernate.validator.internal.metadata.raw.ConstrainedElement;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.xml.AbstractStaxBuilder;
/**
* Builder for definition of all bean constraints.
*
* @author Marko Bekhta
*/
class BeanStaxBuilder extends AbstractStaxBuilder {
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" );
private static final QName CLASS_QNAME = new QName( "class" );
private static final String BEAN_QNAME_LOCAL_PART = "bean";
private final ClassLoadingHelper classLoadingHelper;
private final ConstraintHelper constraintHelper;
private final TypeResolutionHelper typeResolutionHelper;
private final ValueExtractorManager valueExtractorManager;
private final DefaultPackageStaxBuilder defaultPackageStaxBuilder;
private final AnnotationProcessingOptionsImpl annotationProcessingOptions;
private final Map, List>> defaultSequences;
protected String className;
protected Optional ignoreAnnotations;
private ClassConstraintTypeStaxBuilder classConstraintTypeStaxBuilder;
private final List constrainedFieldStaxBuilders;
private final List constrainedGetterStaxBuilders;
private final List constrainedMethodStaxBuilders;
private final List constrainedConstructorStaxBuilders;
BeanStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper,
TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager,
DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions,
Map, List>> defaultSequences) {
this.classLoadingHelper = classLoadingHelper;
this.defaultPackageStaxBuilder = defaultPackageStaxBuilder;
this.constraintHelper = constraintHelper;
this.typeResolutionHelper = typeResolutionHelper;
this.valueExtractorManager = valueExtractorManager;
this.annotationProcessingOptions = annotationProcessingOptions;
this.defaultSequences = defaultSequences;
this.constrainedFieldStaxBuilders = new ArrayList<>();
this.constrainedGetterStaxBuilders = new ArrayList<>();
this.constrainedMethodStaxBuilders = new ArrayList<>();
this.constrainedConstructorStaxBuilders = new ArrayList<>();
}
@Override
protected String getAcceptableQName() {
return BEAN_QNAME_LOCAL_PART;
}
@Override
protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException {
this.className = readAttribute( xmlEvent.asStartElement(), CLASS_QNAME ).get();
this.ignoreAnnotations = readAttribute( xmlEvent.asStartElement(), IGNORE_ANNOTATIONS_QNAME ).map( Boolean::parseBoolean );
ConstrainedFieldStaxBuilder fieldStaxBuilder = getNewConstrainedFieldStaxBuilder();
ConstrainedGetterStaxBuilder getterStaxBuilder = getNewConstrainedGetterStaxBuilder();
ConstrainedMethodStaxBuilder methodStaxBuilder = getNewConstrainedMethodStaxBuilder();
ConstrainedConstructorStaxBuilder constructorStaxBuilder = getNewConstrainedConstructorStaxBuilder();
ClassConstraintTypeStaxBuilder localClassConstraintTypeStaxBuilder = new ClassConstraintTypeStaxBuilder(
classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager,
defaultPackageStaxBuilder, annotationProcessingOptions, defaultSequences
);
while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) {
xmlEvent = xmlEventReader.nextEvent();
if ( fieldStaxBuilder.process( xmlEventReader, xmlEvent ) ) {
constrainedFieldStaxBuilders.add( fieldStaxBuilder );
fieldStaxBuilder = getNewConstrainedFieldStaxBuilder();
}
else if ( getterStaxBuilder.process( xmlEventReader, xmlEvent ) ) {
constrainedGetterStaxBuilders.add( getterStaxBuilder );
getterStaxBuilder = getNewConstrainedGetterStaxBuilder();
}
else if ( methodStaxBuilder.process( xmlEventReader, xmlEvent ) ) {
constrainedMethodStaxBuilders.add( methodStaxBuilder );
methodStaxBuilder = getNewConstrainedMethodStaxBuilder();
}
else if ( constructorStaxBuilder.process( xmlEventReader, xmlEvent ) ) {
constrainedConstructorStaxBuilders.add( constructorStaxBuilder );
constructorStaxBuilder = getNewConstrainedConstructorStaxBuilder();
}
else if ( localClassConstraintTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) {
classConstraintTypeStaxBuilder = localClassConstraintTypeStaxBuilder;
}
}
}
private ConstrainedFieldStaxBuilder getNewConstrainedFieldStaxBuilder() {
return new ConstrainedFieldStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions );
}
private ConstrainedGetterStaxBuilder getNewConstrainedGetterStaxBuilder() {
return new ConstrainedGetterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions );
}
private ConstrainedMethodStaxBuilder getNewConstrainedMethodStaxBuilder() {
return new ConstrainedMethodStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions );
}
private ConstrainedConstructorStaxBuilder getNewConstrainedConstructorStaxBuilder() {
return new ConstrainedConstructorStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions );
}
void build(Set> processedClasses, Map, Set> constrainedElementsByType) {
Class beanClass = classLoadingHelper.loadClass( className, defaultPackageStaxBuilder.build().orElse( "" ) );
checkClassHasNotBeenProcessed( processedClasses, beanClass );
// update annotation ignores
// NOTE: if there was no ignoreAnnotations attribute specified on a bean
// we use `true` as a default
annotationProcessingOptions.ignoreAnnotationConstraintForClass(
beanClass,
ignoreAnnotations.orElse( true )
);
if ( classConstraintTypeStaxBuilder != null ) {
addConstrainedElements(
constrainedElementsByType,
beanClass,
Collections.singleton( classConstraintTypeStaxBuilder.build( beanClass ) )
);
}
List alreadyProcessedFieldNames = new ArrayList<>( constrainedFieldStaxBuilders.size() );
addConstrainedElements(
constrainedElementsByType,
beanClass, constrainedFieldStaxBuilders.stream()
.map( builder -> builder.build( beanClass, alreadyProcessedFieldNames ) )
.collect( Collectors.toList() )
);
List alreadyProcessedGetterNames = new ArrayList<>( constrainedGetterStaxBuilders.size() );
addConstrainedElements(
constrainedElementsByType,
beanClass,
constrainedGetterStaxBuilders.stream()
.map( builder -> builder.build( beanClass, alreadyProcessedGetterNames ) )
.collect( Collectors.toList() )
);
List alreadyProcessedMethods = new ArrayList<>( constrainedMethodStaxBuilders.size() );
addConstrainedElements(
constrainedElementsByType,
beanClass,
constrainedMethodStaxBuilders.stream()
.map( builder -> builder.build( beanClass, alreadyProcessedMethods ) )
.collect( Collectors.toList() )
);
List> alreadyProcessedConstructors = new ArrayList<>( constrainedConstructorStaxBuilders.size() );
addConstrainedElements(
constrainedElementsByType,
beanClass,
constrainedConstructorStaxBuilders.stream()
.map( builder -> builder.build( beanClass, alreadyProcessedConstructors ) )
.collect( Collectors.toList() )
);
}
private void addConstrainedElements(Map, Set> constrainedElementsbyType, Class beanClass, Collection newConstrainedElements) {
if ( constrainedElementsbyType.containsKey( beanClass ) ) {
Set existingConstrainedElements = constrainedElementsbyType.get( beanClass );
for ( ConstrainedElement constrainedElement : newConstrainedElements ) {
if ( existingConstrainedElements.contains( constrainedElement ) ) {
throw LOG.getConstrainedElementConfiguredMultipleTimesException(
constrainedElement.toString()
);
}
}
existingConstrainedElements.addAll( newConstrainedElements );
}
else {
Set tmpSet = newHashSet();
tmpSet.addAll( newConstrainedElements );
constrainedElementsbyType.put( beanClass, tmpSet );
}
}
private void checkClassHasNotBeenProcessed(Set> processedClasses, Class beanClass) {
if ( processedClasses.contains( beanClass ) ) {
throw LOG.getBeanClassHasAlreadyBeenConfiguredInXmlException( beanClass );
}
processedClasses.add( beanClass );
}
}