org.hibernate.validator.internal.xml.mapping.GroupConversionStaxBuilder Maven / Gradle / Ivy
/*
* 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 java.lang.invoke.MethodHandles;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.validation.groups.Default;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
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 group conversions.
*
* @author Marko Bekhta
*/
class GroupConversionStaxBuilder extends AbstractStaxBuilder {
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
private static final String GROUP_CONVERSION_TYPE_QNAME_LOCAL_PART = "convert-group";
private static final QName FROM_QNAME = new QName( "from" );
private static final QName TO_QNAME = new QName( "to" );
private static final String DEFAULT_GROUP_NAME = Default.class.getName();
private final ClassLoadingHelper classLoadingHelper;
private final DefaultPackageStaxBuilder defaultPackageStaxBuilder;
private final Map> groupConversionRules;
GroupConversionStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) {
this.classLoadingHelper = classLoadingHelper;
this.defaultPackageStaxBuilder = defaultPackageStaxBuilder;
this.groupConversionRules = new HashMap<>();
}
@Override
protected String getAcceptableQName() {
return GROUP_CONVERSION_TYPE_QNAME_LOCAL_PART;
}
@Override
protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) {
StartElement startElement = xmlEvent.asStartElement();
String from = readAttribute( startElement, FROM_QNAME ).orElse( DEFAULT_GROUP_NAME );
String to = readAttribute( startElement, TO_QNAME ).get();
groupConversionRules.merge(
from,
Collections.singletonList( to ),
(v1, v2) -> Stream.concat( v1.stream(), v2.stream() ).collect( Collectors.toList() )
);
}
Map, Class> build() {
String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" );
Map, List>> resultingMapping = groupConversionRules.entrySet().stream()
.collect(
// Using groupingBy collector to prevent possible loss of information
// as a string value in `from` could possibly contain both qualified and non qualified
// version of a same class from the default package.
Collectors.groupingBy(
entry -> classLoadingHelper.loadClass( entry.getKey(), defaultPackage ),
Collectors.collectingAndThen(
Collectors.toList(),
entries -> entries.stream()
.flatMap( entry -> entry.getValue().stream() )
.map( className -> classLoadingHelper.loadClass( className, defaultPackage ) )
.collect( Collectors.toList() )
)
)
);
// in case of any duplicates in conversion rules we need to throw an exception:
for ( Map.Entry, List>> entry : resultingMapping.entrySet() ) {
if ( entry.getValue().size() > 1 ) {
throw LOG.getMultipleGroupConversionsForSameSourceException(
entry.getKey(),
entry.getValue()
);
}
}
return resultingMapping.entrySet().stream()
.collect( Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().get( 0 )
) );
}
}