HHH-7919 : Miscellaneous bugfixes

This commit is contained in:
Strong Liu 2013-07-07 16:55:06 +08:00
parent 53d6d2b9a6
commit 346f877a2a
12 changed files with 212 additions and 911 deletions

View File

@ -70,7 +70,6 @@ public interface AnnotationBindingContext extends BindingContext {
*/
MemberResolver getMemberResolver();
Iterable<IdentifierGeneratorSource> extractIdentifierGeneratorSources(IdentifierGeneratorSourceContainer container);
IdentifierGeneratorDefinition findIdGenerator(String name);
}

View File

@ -55,8 +55,6 @@ public class AnnotationBindingContextImpl implements AnnotationBindingContext {
private final ValueHolder<ClassLoaderService> classLoaderService;
private final IndexView index;
private final IdentifierGeneratorExtractionDelegate identifierGeneratorSourceCreationDelegate;
/**
* Constructor
*
@ -76,9 +74,6 @@ public class AnnotationBindingContextImpl implements AnnotationBindingContext {
}
);
this.index = index;
this.identifierGeneratorSourceCreationDelegate = new IdentifierGeneratorExtractionDelegate(
metadata.getOptions().useNewIdentifierGenerators()
);
}
@Override
@ -102,11 +97,6 @@ public class AnnotationBindingContextImpl implements AnnotationBindingContext {
return TYPE_RESOLVER;
}
@Override
public Iterable<IdentifierGeneratorSource> extractIdentifierGeneratorSources(IdentifierGeneratorSourceContainer container) {
return identifierGeneratorSourceCreationDelegate.extractIdentifierGeneratorSources( container );
}
@Override
public IdentifierGeneratorDefinition findIdGenerator(String name) {
return getMetadataImplementor().getIdGenerator( name );

View File

@ -24,6 +24,7 @@
package org.hibernate.metamodel.internal.source.annotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -36,6 +37,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.internal.MetadataImpl;
import org.hibernate.metamodel.internal.source.annotations.global.FetchProfileProcessor;
import org.hibernate.metamodel.internal.source.annotations.global.IdGeneratorProcessor;
import org.hibernate.metamodel.internal.source.annotations.global.QueryProcessor;
import org.hibernate.metamodel.internal.source.annotations.global.SqlResultSetProcessor;
import org.hibernate.metamodel.internal.source.annotations.global.TableProcessor;
@ -73,80 +75,44 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
metadata.setGloballyQuotedIdentifiers( true );
}
bindingContext = new AnnotationBindingContextImpl( metadata, jandexView );
this.bindingContext = new AnnotationBindingContextImpl( metadata, jandexView );
}
@Override
public Iterable<TypeDescriptorSource> extractTypeDefinitionSources() {
assertBindingContextExists();
List<TypeDescriptorSource> typeDescriptorSources = new ArrayList<TypeDescriptorSource>();
Collection<AnnotationInstance> annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TYPE_DEF );
Collection<AnnotationInstance> annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
HibernateDotNames.TYPE_DEF,
HibernateDotNames.TYPE_DEFS
);
for ( AnnotationInstance typeDef : annotations ) {
typeDescriptorSources.add( new TypeDescriptorSourceImpl( typeDef ) );
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TYPE_DEFS );
for ( AnnotationInstance typeDefs : annotations ) {
AnnotationInstance[] typeDefAnnotations = JandexHelper.getValue(
typeDefs,
"value",
AnnotationInstance[].class
);
for ( AnnotationInstance typeDef : typeDefAnnotations ) {
typeDescriptorSources.add( new TypeDescriptorSourceImpl( typeDef ) );
}
}
return typeDescriptorSources;
}
private void assertBindingContextExists() {
if ( bindingContext == null ) {
throw new AssertionFailure( "The binding context should exist. Has prepare been called!?" );
}
}
@Override
public Iterable<FilterDefinitionSource> extractFilterDefinitionSources() {
assertBindingContextExists();
List<FilterDefinitionSource> filterDefinitionSources = new ArrayList<FilterDefinitionSource>();
Collection<AnnotationInstance> annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FILTER_DEF );
Collection<AnnotationInstance> annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
HibernateDotNames.FILTER_DEF,
HibernateDotNames.FILTER_DEFS
);
for ( AnnotationInstance filterDef : annotations ) {
filterDefinitionSources.add( new FilterDefinitionSourceImpl( filterDef ) );
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FILTER_DEFS );
for ( AnnotationInstance filterDefs : annotations ) {
AnnotationInstance[] filterDefAnnotations = JandexHelper.getValue(
filterDefs,
"value",
AnnotationInstance[].class
);
for ( AnnotationInstance filterDef : filterDefAnnotations ) {
filterDefinitionSources.add( new FilterDefinitionSourceImpl( filterDef ) );
}
}
return filterDefinitionSources;
}
@Override
public Iterable<IdentifierGeneratorSource> extractGlobalIdentifierGeneratorSources() {
assertBindingContextExists();
return bindingContext.extractIdentifierGeneratorSources(
new IdentifierGeneratorSourceContainerImpl() {
@Override
protected Collection<AnnotationInstance> getAnnotations(DotName name) {
return bindingContext.getIndex().getAnnotations( name );
}
}
);
return IdGeneratorProcessor.extractGlobalIdentifierGeneratorSources( bindingContext );
}
@Override
public Iterable<EntityHierarchy> extractEntityHierarchies() {
assertBindingContextExists();
// need to order our annotated entities into an order we can process
return EntityHierarchyBuilder.createEntityHierarchies( bindingContext );
}

View File

@ -1,292 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.metamodel.internal.source.annotations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.GenerationType;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.logging.Logger;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.id.MultipleHiLoPerTableGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.SequenceHiLoGenerator;
import org.hibernate.id.TableHiLoGenerator;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.id.enhanced.TableGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource;
/**
* @author Steve Ebersole
*/
public class IdentifierGeneratorExtractionDelegate {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
IdentifierGeneratorExtractionDelegate.class.getName()
);
private final boolean useNewIdentifierGenerators;
public IdentifierGeneratorExtractionDelegate(boolean useNewIdentifierGenerators) {
this.useNewIdentifierGenerators = useNewIdentifierGenerators;
}
public Iterable<IdentifierGeneratorSource> extractIdentifierGeneratorSources(IdentifierGeneratorSourceContainer container) {
List<IdentifierGeneratorSource> identifierGeneratorSources = new ArrayList<IdentifierGeneratorSource>();
processIdentifierGeneratorSources( identifierGeneratorSources, container );
return identifierGeneratorSources;
}
private void processIdentifierGeneratorSources(
List<IdentifierGeneratorSource> identifierGeneratorSources,
IdentifierGeneratorSourceContainer identifierGeneratorSourceContainer) {
processSequenceGenerators(
identifierGeneratorSources,
identifierGeneratorSourceContainer.getSequenceGeneratorSources()
);
processTableGenerators(
identifierGeneratorSources,
identifierGeneratorSourceContainer.getTableGeneratorSources()
);
processGenericGenerators(
identifierGeneratorSources,
identifierGeneratorSourceContainer.getGenericGeneratorSources()
);
}
private void processSequenceGenerators(
List<IdentifierGeneratorSource> identifierGeneratorSources,
Collection<AnnotationInstance> generatorAnnotations) {
for ( AnnotationInstance generatorAnnotation : generatorAnnotations ) {
final String generatorName = JandexHelper.getValue( generatorAnnotation, "name", String.class );
final String generatorImplementationName = EnumConversionHelper.generationTypeToGeneratorStrategyName(
GenerationType.SEQUENCE,
useNewIdentifierGenerators
);
Map<String, String> parameterMap = new HashMap<String, String>();
final String sequenceName = JandexHelper.getValue( generatorAnnotation, "sequenceName", String.class );
if ( StringHelper.isNotEmpty( sequenceName ) ) {
parameterMap.put( SequenceStyleGenerator.SEQUENCE_PARAM, sequenceName );
}
if ( useNewIdentifierGenerators ) {
final String catalog = JandexHelper.getValue( generatorAnnotation, "catalog", String.class );
if ( StringHelper.isNotEmpty( catalog ) ) {
parameterMap.put( PersistentIdentifierGenerator.CATALOG, catalog );
}
final String schema = JandexHelper.getValue( generatorAnnotation, "schema", String.class );
if ( StringHelper.isNotEmpty( schema ) ) {
parameterMap.put( PersistentIdentifierGenerator.SCHEMA, schema );
}
parameterMap.put(
SequenceStyleGenerator.INCREMENT_PARAM,
String.valueOf( JandexHelper.getValue( generatorAnnotation, "allocationSize", Integer.class ) )
);
parameterMap.put(
SequenceStyleGenerator.INITIAL_PARAM,
String.valueOf( JandexHelper.getValue( generatorAnnotation, "initialValue", Integer.class ) )
);
}
else {
if ( JandexHelper.getValue( generatorAnnotation, "initialValue", Integer.class ) != 1 ) {
LOG.unsupportedInitialValue( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS );
}
parameterMap.put(
SequenceHiLoGenerator.MAX_LO,
String.valueOf( JandexHelper.getValue( generatorAnnotation, "allocationSize", Integer.class ) - 1 )
);
}
identifierGeneratorSources.add(
new IdentifierGeneratorSourceImpl( generatorName, generatorImplementationName, parameterMap )
);
}
}
private void processTableGenerators(
List<IdentifierGeneratorSource> identifierGeneratorSources,
Collection<AnnotationInstance> annotations) {
for ( AnnotationInstance generatorAnnotation : annotations ) {
final String generatorName = JandexHelper.getValue( generatorAnnotation, "name", String.class );
final String generatorImplementationName = EnumConversionHelper.generationTypeToGeneratorStrategyName(
GenerationType.TABLE,
useNewIdentifierGenerators
);
Map<String, String> parameterMap = new HashMap<String, String>();
final String catalog = JandexHelper.getValue( generatorAnnotation, "catalog", String.class );
if ( StringHelper.isNotEmpty( catalog ) ) {
parameterMap.put( PersistentIdentifierGenerator.CATALOG, catalog );
}
final String schema = JandexHelper.getValue( generatorAnnotation, "schema", String.class );
if ( StringHelper.isNotEmpty( schema ) ) {
parameterMap.put( PersistentIdentifierGenerator.SCHEMA, schema );
}
if ( useNewIdentifierGenerators ) {
parameterMap.put( TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" );
final String tableName = JandexHelper.getValue( generatorAnnotation, "table", String.class );
if ( StringHelper.isNotEmpty( tableName ) ) {
parameterMap.put( TableGenerator.TABLE_PARAM, tableName );
}
final String segmentColumnName = JandexHelper.getValue(
generatorAnnotation,
"pkColumnName",
String.class
);
if ( StringHelper.isNotEmpty( segmentColumnName ) ) {
parameterMap.put( TableGenerator.SEGMENT_COLUMN_PARAM, segmentColumnName );
}
final String segmentColumnValue = JandexHelper.getValue( generatorAnnotation, "pkColumnValue", String.class );
if ( StringHelper.isNotEmpty( segmentColumnValue ) ) {
parameterMap.put( TableGenerator.SEGMENT_VALUE_PARAM, segmentColumnValue );
}
final String valueColumnName = JandexHelper.getValue( generatorAnnotation, "valueColumnName", String.class );
if ( StringHelper.isNotEmpty( valueColumnName ) ) {
parameterMap.put( TableGenerator.VALUE_COLUMN_PARAM, valueColumnName );
}
parameterMap.put(
TableGenerator.INCREMENT_PARAM,
String.valueOf( JandexHelper.getValue( generatorAnnotation, "allocationSize", Integer.class ) )
);
parameterMap.put(
TableGenerator.INITIAL_PARAM,
String.valueOf( JandexHelper.getValue( generatorAnnotation, "initialValue", Integer.class ) + 1 )
);
}
else {
final String tableName = JandexHelper.getValue( generatorAnnotation, "table", String.class );
if ( StringHelper.isNotEmpty( tableName ) ) {
parameterMap.put( MultipleHiLoPerTableGenerator.ID_TABLE, tableName );
}
final String segmentColumnName = JandexHelper.getValue( generatorAnnotation, "pkColumnName", String.class );
if ( StringHelper.isNotEmpty( segmentColumnName ) ) {
parameterMap.put( MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, segmentColumnName );
}
final String segmentColumnValue = JandexHelper.getValue( generatorAnnotation, "pkColumnValue", String.class );
if ( StringHelper.isNotEmpty( segmentColumnValue ) ) {
parameterMap.put( MultipleHiLoPerTableGenerator.PK_VALUE_NAME, segmentColumnValue );
}
final String valueColumnName = JandexHelper.getValue( generatorAnnotation, "valueColumnName", String.class );
if ( StringHelper.isNotEmpty( valueColumnName ) ) {
parameterMap.put( MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, valueColumnName );
}
parameterMap.put(
TableHiLoGenerator.MAX_LO,
String.valueOf( JandexHelper.getValue( generatorAnnotation, "allocationSize", Integer.class ) - 1 )
);
}
if ( JandexHelper.getValue( generatorAnnotation, "uniqueConstraints", AnnotationInstance[].class ).length > 0 ) {
LOG.ignoringTableGeneratorConstraints( generatorName );
}
identifierGeneratorSources.add(
new IdentifierGeneratorSourceImpl( generatorName, generatorImplementationName, parameterMap )
);
}
}
private void processGenericGenerators(
List<IdentifierGeneratorSource> identifierGeneratorSources,
Collection<AnnotationInstance> genericGeneratorSources) {
for ( AnnotationInstance generatorAnnotation : genericGeneratorSources ) {
Map<String, String> parameterMap = new HashMap<String, String>();
AnnotationInstance[] parameterAnnotations = JandexHelper.getValue(
generatorAnnotation,
"parameters",
AnnotationInstance[].class
);
for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) {
parameterMap.put(
JandexHelper.getValue( parameterAnnotation, "name", String.class ),
JandexHelper.getValue( parameterAnnotation, "value", String.class )
);
}
identifierGeneratorSources.add(
new IdentifierGeneratorSourceImpl(
JandexHelper.getValue( generatorAnnotation, "name", String.class ),
JandexHelper.getValue( generatorAnnotation, "strategy", String.class ),
parameterMap
)
);
}
}
private static class IdentifierGeneratorSourceImpl implements IdentifierGeneratorSource {
private final String generatorName;
private final String generatorImplementationName;
private final Map<String, String> parameterMap;
public IdentifierGeneratorSourceImpl(
String generatorName,
String generatorImplementationName,
Map<String, String> parameterMap) {
this.generatorName = generatorName;
this.generatorImplementationName = generatorImplementationName;
this.parameterMap = parameterMap;
}
@Override
public String getGeneratorName() {
return generatorName;
}
@Override
public String getGeneratorImplementationName() {
return generatorImplementationName;
}
@Override
public Map<String, String> getParameters() {
return parameterMap;
}
}
}

View File

@ -25,6 +25,7 @@ package org.hibernate.metamodel.internal.source.annotations.attribute;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -457,28 +458,16 @@ public class AssociationAttribute extends MappedAttribute {
}
private void determineJoinColumnAnnotations(Map<DotName, List<AnnotationInstance>> annotations) {
// single @JoinColumn
AnnotationInstance joinColumnAnnotation = JandexHelper.getSingleAnnotation(
Collection<AnnotationInstance> joinColumnAnnotations = JandexHelper.getAnnotations(
annotations,
JPADotNames.JOIN_COLUMN
JPADotNames.JOIN_COLUMN,
JPADotNames.JOIN_COLUMNS,
true
);
if ( joinColumnAnnotation != null ) {
for ( AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) {
joinColumnValues.add( new Column( joinColumnAnnotation ) );
}
// @JoinColumns
AnnotationInstance joinColumnsAnnotation = JandexHelper.getSingleAnnotation(
annotations,
JPADotNames.JOIN_COLUMNS
);
if ( joinColumnsAnnotation != null ) {
List<AnnotationInstance> columnsList = Arrays.asList(
JandexHelper.getValue( joinColumnsAnnotation, "value", AnnotationInstance[].class )
);
for ( AnnotationInstance annotation : columnsList ) {
joinColumnValues.add( new Column( annotation ) );
}
}
// @JoinColumn as part of @CollectionTable
AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation(

View File

@ -98,7 +98,6 @@ public class BasicAttribute extends MappedAttribute {
private final String customWriteFragment;
private final String customReadFragment;
private final Map<String,IdentifierGeneratorDefinition> localIdentifierGeneratorDefinitionMap;
private AttributeTypeResolver resolver;
public static BasicAttribute createSimpleAttribute(
@ -135,7 +134,6 @@ public class BasicAttribute extends MappedAttribute {
}
if ( isId() ) {
localIdentifierGeneratorDefinitionMap = buildAttributeLocalIdentifierGeneratorDefinitions();
// an id must be unique and cannot be nullable
for ( Column columnValue : getColumnValues() ) {
columnValue.setUnique( true );
@ -144,7 +142,6 @@ public class BasicAttribute extends MappedAttribute {
identifierGeneratorDefinition = checkGeneratedValueAnnotation();
}
else {
localIdentifierGeneratorDefinitionMap = Collections.EMPTY_MAP;
identifierGeneratorDefinition = null;
}
@ -334,7 +331,7 @@ public class BasicAttribute extends MappedAttribute {
IdentifierGeneratorDefinition generator = null;
String name = JandexHelper.getValue( generatedValueAnnotation, "generator", String.class );
if ( StringHelper.isNotEmpty( name ) ) {
generator = locateIdentifierGeneratorDefinition( name );
generator = getContext().findIdGenerator( name );
if ( generator == null ) {
throw new MappingException( String.format( "Unable to find named generator %s", getRole() ), getContext().getOrigin() );
}
@ -350,42 +347,6 @@ public class BasicAttribute extends MappedAttribute {
return generator;
}
protected IdentifierGeneratorDefinition locateIdentifierGeneratorDefinition(String name) {
// look locally first
IdentifierGeneratorDefinition generator = localIdentifierGeneratorDefinitionMap.get( name );
if ( generator == null ) {
// if not found locally, look "upward"
generator = getContext().findIdGenerator( name );
}
return generator;
}
protected Map<String,IdentifierGeneratorDefinition> buildAttributeLocalIdentifierGeneratorDefinitions() {
Iterable<IdentifierGeneratorSource> identifierGeneratorSources = getContext().extractIdentifierGeneratorSources(
new IdentifierGeneratorSourceContainerImpl() {
@Override
protected Collection<AnnotationInstance> getAnnotations(DotName name) {
return annotations().get( name );
}
}
);
Map<String,IdentifierGeneratorDefinition> map = new HashMap<String, IdentifierGeneratorDefinition>();
for ( IdentifierGeneratorSource source : identifierGeneratorSources ) {
map.put(
source.getGeneratorName(),
new IdentifierGeneratorDefinition(
source.getGeneratorName(),
source.getGeneratorImplementationName(),
source.getParameters()
)
);
}
return map;
}
@Override
public AttributeTypeResolver getHibernateTypeResolver() {
if ( resolver == null ) {

View File

@ -23,15 +23,9 @@
*/
package org.hibernate.metamodel.internal.source.annotations.entity;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.classmate.MemberResolver;
import com.fasterxml.classmate.TypeResolver;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.hibernate.cfg.NamingStrategy;
@ -40,7 +34,6 @@ import org.hibernate.jaxb.spi.Origin;
import org.hibernate.jaxb.spi.SourceType;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.IdentifierGeneratorSourceContainer;
import org.hibernate.metamodel.internal.source.annotations.IdentifierGeneratorSourceContainerImpl;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.hibernate.metamodel.spi.domain.Type;
@ -59,35 +52,9 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind
private final AnnotationBindingContext contextDelegate;
private final Origin origin;
private final Map<String,IdentifierGeneratorDefinition> localIdentifierGeneratorDefinitionMap;
public EntityBindingContext(AnnotationBindingContext contextDelegate, ConfiguredClass source) {
this.contextDelegate = contextDelegate;
this.origin = new Origin( SourceType.ANNOTATION, source.getName() );
this.localIdentifierGeneratorDefinitionMap = processLocalIdentifierGeneratorDefinitions( source.getClassInfo() );
}
private Map<String,IdentifierGeneratorDefinition> processLocalIdentifierGeneratorDefinitions(final ClassInfo classInfo) {
Iterable<IdentifierGeneratorSource> identifierGeneratorSources = extractIdentifierGeneratorSources(
new IdentifierGeneratorSourceContainerImpl() {
@Override
protected Collection<AnnotationInstance> getAnnotations(DotName name) {
return classInfo.annotations().get( name );
}
}
);
Map<String,IdentifierGeneratorDefinition> map = new HashMap<String, IdentifierGeneratorDefinition>();
for ( IdentifierGeneratorSource source : identifierGeneratorSources ) {
map.put(
source.getGeneratorName(),
new IdentifierGeneratorDefinition(
source.getGeneratorName(),
source.getGeneratorImplementationName(),
source.getParameters()
)
);
}
return map;
}
@Override
@ -177,10 +144,6 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind
@Override
public IdentifierGeneratorDefinition findIdGenerator(String name) {
IdentifierGeneratorDefinition definition = localIdentifierGeneratorDefinitionMap.get( name );
if ( definition == null ) {
definition= contextDelegate.findIdGenerator( name );
}
return definition;
return contextDelegate.findIdGenerator( name );
}
}

View File

@ -23,8 +23,10 @@
*/
package org.hibernate.metamodel.internal.source.annotations.global;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.GenerationType;
import javax.persistence.SequenceGenerator;
@ -50,6 +52,7 @@ import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource;
/**
* Binds {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and
@ -73,49 +76,47 @@ public class IdGeneratorProcessor {
*
* @param bindingContext the context for annotation binding
*/
public static void bind(AnnotationBindingContext bindingContext) {
public static Iterable<IdentifierGeneratorSource> extractGlobalIdentifierGeneratorSources(AnnotationBindingContext bindingContext) {
List<IdentifierGeneratorSource> identifierGeneratorSources = new ArrayList<IdentifierGeneratorSource>();
Collection<AnnotationInstance> annotations = bindingContext.getIndex()
.getAnnotations( JPADotNames.SEQUENCE_GENERATOR );
for ( AnnotationInstance generator : annotations ) {
bindSequenceGenerator( bindingContext.getMetadataImplementor(), generator );
bindSequenceGenerator( bindingContext.getMetadataImplementor(), generator, identifierGeneratorSources );
}
annotations = bindingContext.getIndex().getAnnotations( JPADotNames.TABLE_GENERATOR );
for ( AnnotationInstance generator : annotations ) {
bindTableGenerator( bindingContext.getMetadataImplementor(), generator );
bindTableGenerator( bindingContext.getMetadataImplementor(), generator, identifierGeneratorSources );
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.GENERIC_GENERATOR );
annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
HibernateDotNames.GENERIC_GENERATOR,
HibernateDotNames.GENERIC_GENERATORS
);
for ( AnnotationInstance generator : annotations ) {
bindGenericGenerator( bindingContext.getMetadataImplementor(), generator );
bindGenericGenerator( generator, identifierGeneratorSources );
}
return identifierGeneratorSources;
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.GENERIC_GENERATORS );
for ( AnnotationInstance generators : annotations ) {
for ( AnnotationInstance generator : JandexHelper.getValue(
generators,
"value",
AnnotationInstance[].class
) ) {
bindGenericGenerator( bindingContext.getMetadataImplementor(), generator );
}
}
}
private static void addStringParameter(AnnotationInstance annotation,
String element,
Map<String, String> parameters,
String parameter) {
private static void addStringParameter(
final AnnotationInstance annotation,
final String element,
final Map<String, String> parameters,
final String parameter) {
String string = JandexHelper.getValue( annotation, element, String.class );
if ( StringHelper.isNotEmpty( string ) ) {
parameters.put( parameter, string );
}
}
private static void bindGenericGenerator(MetadataImplementor metadata, AnnotationInstance generator) {
String name = JandexHelper.getValue( generator, "name", String.class );
Map<String, String> parameterMap = new HashMap<String, String>();
AnnotationInstance[] parameterAnnotations = JandexHelper.getValue(
private static void bindGenericGenerator(
final AnnotationInstance generator,
final List<IdentifierGeneratorSource> identifierGeneratorSources) {
final String name = JandexHelper.getValue( generator, "name", String.class );
final Map<String, String> parameterMap = new HashMap<String, String>();
final AnnotationInstance[] parameterAnnotations = JandexHelper.getValue(
generator,
"parameters",
AnnotationInstance[].class
@ -126,8 +127,8 @@ public class IdGeneratorProcessor {
JandexHelper.getValue( parameterAnnotation, "value", String.class )
);
}
metadata.addIdGenerator(
new IdentifierGeneratorDefinition(
identifierGeneratorSources.add(
new IdentifierGeneratorSourceImpl(
name,
JandexHelper.getValue( generator, "strategy", String.class ),
parameterMap
@ -136,15 +137,21 @@ public class IdGeneratorProcessor {
LOG.tracef( "Add generic generator with name: %s", name );
}
private static void bindSequenceGenerator(MetadataImplementor metadata, AnnotationInstance generator) {
String name = JandexHelper.getValue( generator, "name", String.class );
Map<String, String> parameterMap = new HashMap<String, String>();
addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM );
boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators();
String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
private static void bindSequenceGenerator(
final MetadataImplementor metadata,
final AnnotationInstance generator,
final List<IdentifierGeneratorSource> identifierGeneratorSources) {
final String name = JandexHelper.getValue( generator, "name", String.class );
final boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators();
final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
GenerationType.SEQUENCE,
useNewIdentifierGenerators
);
final Map<String, String> parameterMap = new HashMap<String, String>();
addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM );
if ( useNewIdentifierGenerators ) {
addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG );
addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA );
@ -166,20 +173,26 @@ public class IdGeneratorProcessor {
String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 )
);
}
metadata.addIdGenerator( new IdentifierGeneratorDefinition( name, strategy, parameterMap ) );
identifierGeneratorSources.add( new IdentifierGeneratorSourceImpl( name, strategy, parameterMap ) );
LOG.tracef( "Add sequence generator with name: %s", name );
}
private static void bindTableGenerator(MetadataImplementor metadata, AnnotationInstance generator) {
String name = JandexHelper.getValue( generator, "name", String.class );
Map<String, String> parameterMap = new HashMap<String, String>();
addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG );
addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA );
boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators();
String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
private static void bindTableGenerator(
final MetadataImplementor metadata,
final AnnotationInstance generator,
final List<IdentifierGeneratorSource> identifierGeneratorSources) {
final String name = JandexHelper.getValue( generator, "name", String.class );
final boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators();
final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
GenerationType.TABLE,
useNewIdentifierGenerators
);
final Map<String, String> parameterMap = new HashMap<String, String>();
addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG );
addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA );
if ( useNewIdentifierGenerators ) {
parameterMap.put( TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" );
addStringParameter( generator, "table", parameterMap, TableGenerator.TABLE_PARAM );
@ -188,18 +201,23 @@ public class IdGeneratorProcessor {
addStringParameter( generator, "valueColumnName", parameterMap, TableGenerator.VALUE_COLUMN_PARAM );
parameterMap.put(
TableGenerator.INCREMENT_PARAM,
String.valueOf( JandexHelper.getValue( generator, "allocationSize", String.class ) )
String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) )
);
parameterMap.put(
TableGenerator.INITIAL_PARAM,
String.valueOf( JandexHelper.getValue( generator, "initialValue", String.class ) + 1 )
String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class ) + 1 )
);
}
else {
addStringParameter( generator, "table", parameterMap, MultipleHiLoPerTableGenerator.ID_TABLE );
addStringParameter( generator, "pkColumnName", parameterMap, MultipleHiLoPerTableGenerator.PK_COLUMN_NAME );
addStringParameter( generator, "pkColumnValue", parameterMap, MultipleHiLoPerTableGenerator.PK_VALUE_NAME );
addStringParameter( generator, "valueColumnName", parameterMap, MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME );
addStringParameter(
generator,
"valueColumnName",
parameterMap,
MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME
);
parameterMap.put(
TableHiLoGenerator.MAX_LO,
String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 )
@ -208,7 +226,37 @@ public class IdGeneratorProcessor {
if ( JandexHelper.getValue( generator, "uniqueConstraints", AnnotationInstance[].class ).length > 0 ) {
LOG.ignoringTableGeneratorConstraints( name );
}
metadata.addIdGenerator( new IdentifierGeneratorDefinition( name, strategy, parameterMap ) );
identifierGeneratorSources.add( new IdentifierGeneratorSourceImpl( name, strategy, parameterMap ) );
LOG.tracef( "Add table generator with name: %s", name );
}
private static class IdentifierGeneratorSourceImpl implements IdentifierGeneratorSource {
private final String generatorName;
private final String generatorImplementationName;
private final Map<String, String> parameterMap;
public IdentifierGeneratorSourceImpl(
String generatorName,
String generatorImplementationName,
Map<String, String> parameterMap) {
this.generatorName = generatorName;
this.generatorImplementationName = generatorImplementationName;
this.parameterMap = parameterMap;
}
@Override
public String getGeneratorName() {
return generatorName;
}
@Override
public String getGeneratorImplementationName() {
return generatorImplementationName;
}
@Override
public Map<String, String> getParameters() {
return parameterMap;
}
}
}

View File

@ -85,53 +85,41 @@ public class QueryProcessor {
* @param bindingContext the context for annotation binding
*/
public static void bind(AnnotationBindingContext bindingContext) {
Collection<AnnotationInstance> annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_QUERY );
Collection<AnnotationInstance> annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
JPADotNames.NAMED_QUERY,
JPADotNames.NAMED_QUERIES
);
for ( AnnotationInstance query : annotations ) {
bindNamedQuery( bindingContext.getMetadataImplementor(), query );
}
annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_QUERIES );
for ( AnnotationInstance queries : annotations ) {
for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) {
bindNamedQuery( bindingContext.getMetadataImplementor(), query );
}
}
annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_NATIVE_QUERY );
annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
JPADotNames.NAMED_NATIVE_QUERY,
JPADotNames.NAMED_NATIVE_QUERIES
);
for ( AnnotationInstance query : annotations ) {
bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query );
}
annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_NATIVE_QUERIES );
for ( AnnotationInstance queries : annotations ) {
for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) {
bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query );
}
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_QUERY );
annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
HibernateDotNames.NAMED_QUERY,
HibernateDotNames.NAMED_QUERIES
);
for ( AnnotationInstance query : annotations ) {
bindNamedQuery( bindingContext.getMetadataImplementor(), query );
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_QUERIES );
for ( AnnotationInstance queries : annotations ) {
for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) {
bindNamedQuery( bindingContext.getMetadataImplementor(), query );
}
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY );
annotations = JandexHelper.getAnnotations(
bindingContext.getIndex(),
HibernateDotNames.NAMED_NATIVE_QUERY,
HibernateDotNames.NAMED_NATIVE_QUERIES
);
for ( AnnotationInstance query : annotations ) {
bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query );
}
annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERIES );
for ( AnnotationInstance queries : annotations ) {
for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) {
bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query );
}
}
}
/**

View File

@ -30,6 +30,8 @@ import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@ -199,6 +201,68 @@ public class JandexHelper {
}
}
public static Collection<AnnotationInstance> getAnnotations(
final IndexView indexView,
final DotName singularDotName,
final DotName pluralDotName
) {
List<AnnotationInstance> annotationInstances = new ArrayList<AnnotationInstance>();
annotationInstances.addAll( indexView.getAnnotations( singularDotName ) );
Collection<AnnotationInstance> pluralAnnotations = indexView.getAnnotations( pluralDotName );
for ( AnnotationInstance ann : pluralAnnotations ) {
AnnotationInstance[] typeDefAnnotations = JandexHelper.getValue(
ann,
"value",
AnnotationInstance[].class
);
annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) );
}
return annotationInstances;
}
public static Collection<AnnotationInstance> getAnnotations(
final Map<DotName, List<AnnotationInstance>> annotations,
final DotName singularDotName,
final DotName pluralDotName) {
return getAnnotations( annotations, singularDotName, pluralDotName, false );
}
public static Collection<AnnotationInstance> getAnnotations(
final Map<DotName, List<AnnotationInstance>> annotations,
final DotName singularDotName,
final DotName pluralDotName,
final boolean checkSingle) {
List<AnnotationInstance> annotationInstances = new ArrayList<AnnotationInstance>();
List<AnnotationInstance> list = annotations.get( singularDotName );
if ( list != null ) {
if ( checkSingle ) {
assertSingularAnnotationInstances( list );
}
annotationInstances.addAll( list );
}
Collection<AnnotationInstance> pluralAnnotations = annotations.get( pluralDotName );
if ( pluralAnnotations != null ) {
if ( checkSingle ) {
assertSingularAnnotationInstances( pluralAnnotations );
}
for ( AnnotationInstance ann : pluralAnnotations ) {
AnnotationInstance[] typeDefAnnotations = JandexHelper.getValue(
ann,
"value",
AnnotationInstance[].class
);
annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) );
}
}
return annotationInstances;
}
/**
* @param classInfo the class info from which to retrieve the annotation instance
* @param annotationName the annotation to retrieve from the class info
@ -241,10 +305,18 @@ public class JandexHelper {
if ( annotationList.size() == 1 ) {
return annotationList.get( 0 );
}
assertSingularAnnotationInstances( annotationList );
return null;//only here to make compiler happy
}
private static void assertSingularAnnotationInstances(Collection<AnnotationInstance> annotationInstances) {
if ( annotationInstances.size() > 1 ) {
throw new AssertionFailure(
"Found more than one instance of the annotation "
+ annotationList.get( 0 ).name().toString()
+ ". Expected was one." );
+ annotationInstances.iterator().next().name().toString()
+ ". Expected was one."
);
}
}
/**
@ -258,20 +330,6 @@ public class JandexHelper {
public static AnnotationInstance getSingleAnnotation(Map<DotName, List<AnnotationInstance>> annotations, DotName annotationName)
throws AssertionFailure {
return getSingleAnnotation( annotations, annotationName, null );
// List<AnnotationInstance> annotationList = annotations.get( annotationName );
// if ( annotationList == null ) {
// return null;
// }
// else if ( annotationList.size() == 1 ) {
// return annotationList.get( 0 );
// }
// else {
// throw new AssertionFailure(
// "Found more than one instance of the annotation "
// + annotationList.get( 0 ).name().toString()
// + ". Expected was one."
// );
// }
}
/**

View File

@ -1,369 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.metamodel.source.annotations;
import java.beans.Introspector;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.internal.util.type.PrimitiveWrapperHelper;
/**
* Utility methods for working with the jandex annotation index.
*
* @author Hardy Ferentschik
*/
public class JandexHelper {
private static final Map<String, Object> DEFAULT_VALUES_BY_ELEMENT = new HashMap<String, Object>();
private JandexHelper() {
}
/**
* Retrieves a jandex annotation element value. If the value is {@code null}, the default value specified in the
* annotation class is retrieved instead.
* <p>
* There are two special cases. {@code Class} parameters should be retrieved as strings (and then can later be
* loaded) and enumerated values should be retrieved via {@link #getEnumValue(AnnotationInstance, String, Class)}.
* </p>
*
* @param annotation the annotation containing the element with the supplied name
* @param element the name of the element value to be retrieve
* @param type the type of element to retrieve. The following types are supported:
* <ul>
* <li>Byte</li>
* <li>Short</li>
* <li>Integer</li>
* <li>Character</li>
* <li>Float</li>
* <li>Double</li>
* <li>Long</li>
* <li>Boolean</li>
* <li>String</li>
* <li>AnnotationInstance</li>
*
* @return the value if not {@code null}, else the default value if not
* {@code null}, else {@code null}.
*
* @throws AssertionFailure in case the specified {@code type} is a class instance or the specified type causes a {@code ClassCastException}
* when retrieving the value.
*/
@SuppressWarnings("unchecked")
public static <T> T getValue(AnnotationInstance annotation, String element, Class<T> type) throws AssertionFailure {
if ( Class.class.equals( type ) ) {
throw new AssertionFailure(
"Annotation parameters of type Class should be retrieved as strings (fully qualified class names)"
);
}
if ( type.isPrimitive() ) {
type = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( type ).getWrapperClass();
}
// try getting the untyped value from Jandex
AnnotationValue annotationValue = annotation.value( element );
try {
if ( annotationValue != null ) {
return explicitAnnotationParameter( annotationValue, type );
}
else {
return defaultAnnotationParameter( getDefaultValue( annotation, element ), type );
}
}
catch ( ClassCastException e ) {
throw new AssertionFailure(
String.format(
"the annotation property %s of annotation %s is not of type %s",
element,
annotation.name(),
type.getName()
),
e
);
}
}
/**
* Retrieves a jandex annotation element value, converting it to the supplied enumerated type. If the value is
* <code>null</code>, the default value specified in the annotation class is retrieved instead.
*
* @param <T> an enumerated type
* @param annotation the annotation containing the enumerated element with the supplied name
* @param element the name of the enumerated element value to be retrieve
* @param type the type to which to convert the value before being returned
*
* @return the value converted to the supplied enumerated type if the value is not <code>null</code>, else the default value if
* not <code>null</code>, else <code>null</code>.
*
* @see #getValue(AnnotationInstance, String, Class)
*/
@SuppressWarnings("unchecked")
public static <T extends Enum<T>> T getEnumValue(AnnotationInstance annotation, String element, Class<T> type) {
AnnotationValue val = annotation.value( element );
if ( val == null ) {
return (T) getDefaultValue( annotation, element );
}
return Enum.valueOf( type, val.asEnum() );
}
/**
* Expects a method or field annotation target and returns the property name for this target
*
* @param target the annotation target
*
* @return the property name of the target. For a field it is the field name and for a method name it is
* the method name stripped of 'is', 'has' or 'get'
*/
public static String getPropertyName(AnnotationTarget target) {
if ( !( target instanceof MethodInfo || target instanceof FieldInfo ) ) {
throw new AssertionFailure( "Unexpected annotation target " + target.toString() );
}
if ( target instanceof FieldInfo ) {
return ( (FieldInfo) target ).name();
}
else {
final String methodName = ( (MethodInfo) target ).name();
String propertyName;
if ( methodName.startsWith( "is" ) ) {
propertyName = Introspector.decapitalize( methodName.substring( 2 ) );
}
else if ( methodName.startsWith( "has" ) ) {
propertyName = Introspector.decapitalize( methodName.substring( 3 ) );
}
else if ( methodName.startsWith( "get" ) ) {
propertyName = Introspector.decapitalize( methodName.substring( 3 ) );
}
else {
throw new AssertionFailure( "Expected a method following the Java Bean notation" );
}
return propertyName;
}
}
/**
* @param classInfo the class info from which to retrieve the annotation instance
* @param annotationName the annotation to retrieve from the class info
*
* @return the single annotation defined on the class or {@code null} in case the annotation is not specified at all
*
* @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type.
*/
public static AnnotationInstance getSingleAnnotation(ClassInfo classInfo, DotName annotationName)
throws AssertionFailure {
return getSingleAnnotation( classInfo.annotations(), annotationName );
}
/**
* @param annotations List of annotation instances keyed against their dot name.
* @param annotationName the annotation to retrieve from map
*
* @return the single annotation of the specified dot name or {@code null} in case the annotation is not specified at all
*
* @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type.
*/
public static AnnotationInstance getSingleAnnotation(Map<DotName, List<AnnotationInstance>> annotations, DotName annotationName)
throws AssertionFailure {
List<AnnotationInstance> annotationList = annotations.get( annotationName );
if ( annotationList == null ) {
return null;
}
else if ( annotationList.size() == 1 ) {
return annotationList.get( 0 );
}
else {
throw new AssertionFailure(
"Found more than one instance of the annotation "
+ annotationList.get( 0 ).name().toString()
+ ". Expected was one."
);
}
}
/**
* @param annotations List of annotation instances keyed against their dot name.
* @param annotationName the annotation to check
*
* @return returns {@code true} if the map contains only a single instance of specified annotation or {@code false} otherwise.
*
* @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type.
*/
public static boolean containsSingleAnnotations(Map<DotName, List<AnnotationInstance>> annotations, DotName annotationName)
throws AssertionFailure {
return getSingleAnnotation( annotations, annotationName ) != null;
}
/**
* Creates a jandex index for the specified classes
*
* @param classLoaderService class loader service
* @param classes the classes to index
*
* @return an annotation repository w/ all the annotation discovered in the specified classes
*/
public static Index indexForClass(ClassLoaderService classLoaderService, Class<?>... classes) {
Indexer indexer = new Indexer();
for ( Class<?> clazz : classes ) {
InputStream stream = classLoaderService.locateResourceStream(
clazz.getName().replace( '.', '/' ) + ".class"
);
try {
indexer.index( stream );
}
catch ( IOException e ) {
StringBuilder builder = new StringBuilder();
builder.append( "[" );
int count = 0;
for ( Class<?> c : classes ) {
builder.append( c.getName() );
if ( count < classes.length - 1 ) {
builder.append( "," );
}
count++;
}
builder.append( "]" );
throw new HibernateException( "Unable to create annotation index for " + builder.toString() );
}
}
return indexer.complete();
}
public static Map<DotName, List<AnnotationInstance>> getMemberAnnotations(ClassInfo classInfo, String name) {
if ( classInfo == null ) {
throw new IllegalArgumentException( "classInfo cannot be null" );
}
if ( name == null ) {
throw new IllegalArgumentException( "name cannot be null" );
}
Map<DotName, List<AnnotationInstance>> annotations = new HashMap<DotName, List<AnnotationInstance>>();
for ( List<AnnotationInstance> annotationList : classInfo.annotations().values() ) {
for ( AnnotationInstance instance : annotationList ) {
String targetName = null;
if ( instance.target() instanceof FieldInfo ) {
targetName = ( (FieldInfo) instance.target() ).name();
}
else if ( instance.target() instanceof MethodInfo ) {
targetName = ( (MethodInfo) instance.target() ).name();
}
if ( targetName != null && name.equals( targetName ) ) {
addAnnotationToMap( instance, annotations );
}
}
}
return annotations;
}
private static void addAnnotationToMap(AnnotationInstance instance, Map<DotName, List<AnnotationInstance>> annotations) {
DotName dotName = instance.name();
List<AnnotationInstance> list;
if ( annotations.containsKey( dotName ) ) {
list = annotations.get( dotName );
}
else {
list = new ArrayList<AnnotationInstance>();
annotations.put( dotName, list );
}
list.add( instance );
}
private static Object getDefaultValue(AnnotationInstance annotation, String element) {
String name = annotation.name().toString();
String fqElement = name + '.' + element;
Object val = DEFAULT_VALUES_BY_ELEMENT.get( fqElement );
if ( val != null ) {
return val;
}
try {
val = Index.class.getClassLoader().loadClass( name ).getMethod( element ).getDefaultValue();
DEFAULT_VALUES_BY_ELEMENT.put( fqElement, val );
return val == null ? null : val;
}
catch ( RuntimeException error ) {
throw error;
}
catch ( Exception error ) {
throw new AssertionFailure(
String.format( "The annotation %s does not define a parameter '%s'", name, element ),
error
);
}
}
private static <T> T defaultAnnotationParameter(Object defaultValue, Class<T> type) {
Object returnValue = defaultValue;
// resolve some mismatches between what's stored in jandex and what the defaults are for annotations
// in case of nested annotation arrays, jandex returns arrays of AnnotationInstances, hence we return
// an empty array of this type here
if ( defaultValue.getClass().isArray() && defaultValue.getClass().getComponentType().isAnnotation() ) {
returnValue = new AnnotationInstance[0];
}
return type.cast( returnValue );
}
private static <T> T explicitAnnotationParameter(AnnotationValue annotationValue, Class<T> type) {
Object returnValue = annotationValue.value();
// if the jandex return type is Type we actually try to retrieve a class parameter
// for our purposes we just return the fqcn of the class
if ( returnValue instanceof Type ) {
returnValue = ( (Type) returnValue ).name().toString();
}
// arrays we have to handle explicitly
if ( type.isArray() ) {
AnnotationValue[] values = (AnnotationValue[]) returnValue;
Class<?> componentType = type.getComponentType();
Object[] arr = (Object[]) Array.newInstance( componentType, values.length );
for ( int i = 0; i < values.length; i++ ) {
arr[i] = componentType.cast( values[i].value() );
}
returnValue = arr;
}
return type.cast( returnValue );
}
}