From 77004f5fe25243c399501500b89d97282817f314 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Fri, 8 Jul 2011 18:57:06 +0200 Subject: [PATCH] HHH-6392 Starting to refactor JandexHelper --- .../annotations/entity/EntityBinder.java | 10 +- .../global/FetchProfileBinder.java | 28 +- .../annotations/global/FilterDefBinder.java | 17 +- .../annotations/global/IdGeneratorBinder.java | 52 ++-- .../annotations/global/QueryBinder.java | 26 +- .../annotations/global/TableBinder.java | 16 +- .../annotations/global/TypeDefBinder.java | 37 ++- .../source/annotations/util/JandexHelper.java | 239 ++++++++++-------- .../annotations/util/JandexHelperTest.java | 152 ++++++++--- 9 files changed, 362 insertions(+), 215 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java index e9daaec0e5..c2bc8e74b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java @@ -206,7 +206,7 @@ public class EntityBinder { ); if ( whereAnnotation != null ) { // no null check needed, it is a required attribute - entityBindingState.setWhereFilter( JandexHelper.getValueAsString( whereAnnotation, "clause" ) ); + entityBindingState.setWhereFilter( JandexHelper.getValue( whereAnnotation, "clause", String.class ) ); } } @@ -409,9 +409,9 @@ public class EntityBinder { entityClass.getClassInfo(), JPADotNames.TABLE ); if ( tableAnnotation != null ) { - schemaName = JandexHelper.getValueAsString( tableAnnotation, "schema" ); - catalogName = JandexHelper.getValueAsString( tableAnnotation, "catalog" ); - String explicitTableName = JandexHelper.getValueAsString( tableAnnotation, "name" ); + schemaName = JandexHelper.getValue( tableAnnotation, "schema", String.class); + catalogName = JandexHelper.getValue( tableAnnotation, "catalog", String.class ); + String explicitTableName = JandexHelper.getValue( tableAnnotation, "name", String.class ); if ( StringHelper.isNotEmpty( explicitTableName ) ) { tableName = meta.getNamingStrategy().tableName( explicitTableName ); } @@ -569,7 +569,7 @@ public class EntityBinder { ) ); } - String generator = JandexHelper.getValueAsString( generatedValueAnn, "generator" ); + String generator = JandexHelper.getValue( generatedValueAnn, "generator", String.class ); IdGenerator idGenerator = null; if ( StringHelper.isNotEmpty( generator ) ) { idGenerator = meta.getIdGenerator( generator ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java index 69aee141a0..c3fac4de9a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java @@ -57,29 +57,33 @@ public class FetchProfileBinder { bind( metadata, fetchProfile ); } for ( AnnotationInstance fetchProfiles : jandex.getAnnotations( HibernateDotNames.FETCH_PROFILES ) ) { - for ( AnnotationInstance fetchProfile : JandexHelper.getValueAsArray( fetchProfiles, "value" ) ) { + AnnotationInstance[] fetchProfileAnnotations = JandexHelper.getValue( + fetchProfiles, + "value", + AnnotationInstance[].class + ); + for ( AnnotationInstance fetchProfile : fetchProfileAnnotations ) { bind( metadata, fetchProfile ); } } } private static void bind(MetadataImplementor metadata, AnnotationInstance fetchProfile) { - String name = JandexHelper.getValueAsString( fetchProfile, "name" ); + String name = JandexHelper.getValue( fetchProfile, "name", String.class ); Set fetches = new HashSet(); - for ( AnnotationInstance override : JandexHelper.getValueAsArray( fetchProfile, "fetchOverrides" ) ) { + AnnotationInstance[] overrideAnnotations = JandexHelper.getValue( + fetchProfile, + "fetchOverrides", + AnnotationInstance[].class + ); + for ( AnnotationInstance override : overrideAnnotations ) { FetchMode fetchMode = JandexHelper.getValueAsEnum( override, "mode", FetchMode.class ); if ( !fetchMode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) { throw new MappingException( "Only FetchMode.JOIN is currently supported" ); } - fetches.add( - new Fetch( - JandexHelper.getValueAsString( override, "entity" ), JandexHelper.getValueAsString( - override, - "association" - ), - fetchMode.toString().toLowerCase() - ) - ); + String entityName = JandexHelper.getValue( override, "entity", String.class ); + String associationName = JandexHelper.getValue( override, "association", String.class ); + fetches.add( new Fetch( entityName, associationName, fetchMode.toString().toLowerCase() ) ); } metadata.addFetchProfile( new FetchProfile( name, fetches ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java index 211a3ce29c..48482a77f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java @@ -57,25 +57,30 @@ public class FilterDefBinder { bind( metadata, filterDef ); } for ( AnnotationInstance filterDefs : jandex.getAnnotations( HibernateDotNames.FILTER_DEFS ) ) { - for ( AnnotationInstance filterDef : JandexHelper.getValueAsArray( filterDefs, "value" ) ) { + AnnotationInstance[] filterDefAnnotations = JandexHelper.getValue( + filterDefs, + "value", + AnnotationInstance[].class + ); + for ( AnnotationInstance filterDef : filterDefAnnotations ) { bind( metadata, filterDef ); } } } private static void bind(MetadataImplementor metadata, AnnotationInstance filterDef) { - String name = JandexHelper.getValueAsString( filterDef, "name" ); + String name = JandexHelper.getValue( filterDef, "name", String.class ); Map prms = new HashMap(); - for ( AnnotationInstance prm : JandexHelper.getValueAsArray( filterDef, "parameters" ) ) { + for ( AnnotationInstance prm : JandexHelper.getValue( filterDef, "parameters", AnnotationInstance[].class ) ) { prms.put( - JandexHelper.getValueAsString( prm, "name" ), - metadata.getTypeResolver().heuristicType( JandexHelper.getValueAsString( prm, "type" ) ) + JandexHelper.getValue( prm, "name", String.class ), + metadata.getTypeResolver().heuristicType( JandexHelper.getValue( prm, "type", String.class ) ) ); } metadata.addFilterDefinition( new FilterDefinition( name, - JandexHelper.getValueAsString( filterDef, "defaultCondition" ), + JandexHelper.getValue( filterDef, "defaultCondition", String.class ), prms ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java index 5ea250e72e..d7a202dd1e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java @@ -23,10 +23,10 @@ */ package org.hibernate.metamodel.source.annotations.global; -import javax.persistence.GenerationType; -import javax.persistence.SequenceGenerator; import java.util.HashMap; import java.util.Map; +import javax.persistence.GenerationType; +import javax.persistence.SequenceGenerator; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.Index; @@ -64,7 +64,7 @@ public class IdGeneratorBinder { String element, Map parameters, String parameter) { - String string = JandexHelper.getValueAsString( annotation, element ); + String string = JandexHelper.getValue( annotation, element, String.class ); if ( StringHelper.isNotEmpty( string ) ) { parameters.put( parameter, string ); } @@ -88,30 +88,42 @@ public class IdGeneratorBinder { bindGenericGenerator( metadata, generator ); } for ( AnnotationInstance generators : jandex.getAnnotations( HibernateDotNames.GENERIC_GENERATORS ) ) { - for ( AnnotationInstance generator : JandexHelper.getValueAsArray( generators, "value" ) ) { + for ( AnnotationInstance generator : JandexHelper.getValue( + generators, + "value", + AnnotationInstance[].class + ) ) { bindGenericGenerator( metadata, generator ); } } } private static void bindGenericGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValueAsString( generator, "name" ); - Map prms = new HashMap(); - for ( AnnotationInstance prm : JandexHelper.getValueAsArray( generator, "parameters" ) ) { - prms.put( JandexHelper.getValueAsString( prm, "name" ), JandexHelper.getValueAsString( prm, "value" ) ); + String name = JandexHelper.getValue( generator, "name", String.class ); + Map parameterMap = new HashMap(); + AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( + generator, + "parameters", + AnnotationInstance[].class + ); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + parameterMap.put( + JandexHelper.getValue( parameterAnnotation, "name", String.class ), + JandexHelper.getValue( parameterAnnotation, "value", String.class ) + ); } metadata.addIdGenerator( new IdGenerator( name, - JandexHelper.getValueAsString( generator, "strategy" ), - prms + JandexHelper.getValue( generator, "strategy", String.class ), + parameterMap ) ); LOG.tracef( "Add generic generator with name: %s", name ); } private static void bindSequenceGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValueAsString( generator, "name" ); + String name = JandexHelper.getValue( generator, "name", String.class ); String strategy; Map prms = new HashMap(); addStringParameter( generator, "sequenceName", prms, SequenceStyleGenerator.SEQUENCE_PARAM ); @@ -122,20 +134,20 @@ public class IdGeneratorBinder { addStringParameter( generator, "schema", prms, PersistentIdentifierGenerator.SCHEMA ); prms.put( SequenceStyleGenerator.INCREMENT_PARAM, - String.valueOf( JandexHelper.getValueAsInt( generator, "allocationSize" ) ) + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) ) ); prms.put( SequenceStyleGenerator.INITIAL_PARAM, - String.valueOf( JandexHelper.getValueAsInt( generator, "initialValue" ) ) + String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class ) ) ); } else { - if ( JandexHelper.getValueAsInt( generator, "initialValue" ) != 1 ) { + if ( JandexHelper.getValue( generator, "initialValue", Integer.class ) != 1 ) { LOG.unsupportedInitialValue( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS ); } prms.put( SequenceHiLoGenerator.MAX_LO, - String.valueOf( JandexHelper.getValueAsInt( generator, "allocationSize" ) - 1 ) + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 ) ); } metadata.addIdGenerator( new IdGenerator( name, strategy, prms ) ); @@ -143,7 +155,7 @@ public class IdGeneratorBinder { } private static void bindTableGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValueAsString( generator, "name" ); + String name = JandexHelper.getValue( generator, "name", String.class ); String strategy; Map prms = new HashMap(); addStringParameter( generator, "catalog", prms, PersistentIdentifierGenerator.CATALOG ); @@ -158,11 +170,11 @@ public class IdGeneratorBinder { addStringParameter( generator, "valueColumnName", prms, TableGenerator.VALUE_COLUMN_PARAM ); prms.put( TableGenerator.INCREMENT_PARAM, - String.valueOf( JandexHelper.getValueAsInt( generator, "allocationSize" ) ) + String.valueOf( JandexHelper.getValue( generator, "allocationSize", String.class ) ) ); prms.put( TableGenerator.INITIAL_PARAM, - String.valueOf( JandexHelper.getValueAsInt( generator, "initialValue" ) + 1 ) + String.valueOf( JandexHelper.getValue( generator, "initialValue", String.class ) + 1 ) ); } else { @@ -172,10 +184,10 @@ public class IdGeneratorBinder { addStringParameter( generator, "valueColumnName", prms, MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME ); prms.put( TableHiLoGenerator.MAX_LO, - String.valueOf( JandexHelper.getValueAsInt( generator, "allocationSize" ) - 1 ) + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 ) ); } - if ( JandexHelper.getValueAsArray( generator, "uniqueConstraints" ).length > 0 ) { + if ( JandexHelper.getValue( generator, "uniqueConstraints", AnnotationInstance[].class ).length > 0 ) { LOG.ignoringTableGeneratorConstraints( name ); } metadata.addIdGenerator( new IdGenerator( name, strategy, prms ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java index 1dfbcc98b8..29be2c520c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java @@ -74,7 +74,7 @@ public class QueryBinder { bindNamedQuery( metadata, query ); } for ( AnnotationInstance queries : jandex.getAnnotations( JPADotNames.NAMED_QUERIES ) ) { - for ( AnnotationInstance query : JandexHelper.getValueAsArray( queries, "value" ) ) { + for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { bindNamedQuery( metadata, query ); } } @@ -82,7 +82,7 @@ public class QueryBinder { bindNamedNativeQuery( metadata, query ); } for ( AnnotationInstance queries : jandex.getAnnotations( JPADotNames.NAMED_NATIVE_QUERIES ) ) { - for ( AnnotationInstance query : JandexHelper.getValueAsArray( queries, "value" ) ) { + for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { bindNamedNativeQuery( metadata, query ); } } @@ -90,7 +90,7 @@ public class QueryBinder { bindNamedQuery( metadata, query ); } for ( AnnotationInstance queries : jandex.getAnnotations( HibernateDotNames.NAMED_QUERIES ) ) { - for ( AnnotationInstance query : JandexHelper.getValueAsArray( queries, "value" ) ) { + for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { bindNamedQuery( metadata, query ); } } @@ -98,7 +98,7 @@ public class QueryBinder { bindNamedNativeQuery( metadata, query ); } for ( AnnotationInstance queries : jandex.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERIES ) ) { - for ( AnnotationInstance query : JandexHelper.getValueAsArray( queries, "value" ) ) { + for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { bindNamedNativeQuery( metadata, query ); } } @@ -111,14 +111,14 @@ public class QueryBinder { * @param annotation the named query annotation */ private static void bindNamedQuery(MetadataImplementor metadata, AnnotationInstance annotation) { - String name = JandexHelper.getValueAsString( annotation, "name" ); + String name = JandexHelper.getValue( annotation, "name", String.class ); if ( StringHelper.isEmpty( name ) ) { throw new AnnotationException( "A named query must have a name when used in class or package level" ); } - String query = JandexHelper.getValueAsString( annotation, "query" ); + String query = JandexHelper.getValue( annotation, "query", String.class ); - AnnotationInstance[] hints = JandexHelper.getValueAsArray( annotation, "hints" ); + AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class ); String cacheRegion = getString( hints, QueryHints.CACHE_REGION ); if ( StringHelper.isEmpty( cacheRegion ) ) { @@ -153,16 +153,16 @@ public class QueryBinder { } private static void bindNamedNativeQuery(MetadataImplementor metadata, AnnotationInstance annotation) { - String name = JandexHelper.getValueAsString( annotation, "name" ); + String name = JandexHelper.getValue( annotation, "name", String.class ); if ( StringHelper.isEmpty( name ) ) { throw new AnnotationException( "A named native query must have a name when used in class or package level" ); } - String query = JandexHelper.getValueAsString( annotation, "query" ); + String query = JandexHelper.getValue( annotation, "query", String.class ); - String resultSetMapping = JandexHelper.getValueAsString( annotation, "resultSetMapping" ); + String resultSetMapping = JandexHelper.getValue( annotation, "resultSetMapping", String.class ); - AnnotationInstance[] hints = JandexHelper.getValueAsArray( annotation, "hints" ); + AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class ); boolean cacheable = getBoolean( hints, "org.hibernate.cacheable", name ); String cacheRegion = getString( hints, QueryHints.CACHE_REGION ); @@ -309,8 +309,8 @@ public class QueryBinder { private static String getString(AnnotationInstance[] hints, String element) { for ( AnnotationInstance hint : hints ) { - if ( element.equals( JandexHelper.getValue( hint, "name" ) ) ) { - return JandexHelper.getValueAsString( hint, "value" ); + if ( element.equals( JandexHelper.getValue( hint, "name", String.class ) ) ) { + return JandexHelper.getValue( hint, "value", String.class ); } } return null; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java index fd98079840..e2894b7e66 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java @@ -63,14 +63,14 @@ public class TableBinder { bind( metadata, tableAnnotation ); } for ( AnnotationInstance tables : jandex.getAnnotations( HibernateDotNames.TABLES ) ) { - for ( AnnotationInstance table : JandexHelper.getValueAsArray( tables, "value" ) ) { + for ( AnnotationInstance table : JandexHelper.getValue( tables, "value", AnnotationInstance[].class ) ) { bind( metadata, table ); } } } private static void bind(MetadataImplementor metadata, AnnotationInstance tableAnnotation) { - String tableName = JandexHelper.getValueAsString( tableAnnotation, "appliesTo" ); + String tableName = JandexHelper.getValue( tableAnnotation, "appliesTo", String.class ); ObjectName objectName = new ObjectName( tableName ); Schema schema = metadata.getDatabase().getSchema( objectName.getSchema(), objectName.getCatalog() ); Table table = schema.getTable( objectName.getName() ); @@ -80,18 +80,22 @@ public class TableBinder { } private static void bindHibernateTableAnnotation(Table table, AnnotationInstance tableAnnotation) { - for ( AnnotationInstance indexAnnotation : JandexHelper.getValueAsArray( tableAnnotation, "indexes" ) ) { + for ( AnnotationInstance indexAnnotation : JandexHelper.getValue( + tableAnnotation, + "indexes", + AnnotationInstance[].class + ) ) { bindIndexAnnotation( table, indexAnnotation ); } - String comment = JandexHelper.getValueAsString( tableAnnotation, "comment" ); + String comment = JandexHelper.getValue( tableAnnotation, "comment", String.class ); if ( StringHelper.isNotEmpty( comment ) ) { table.addComment( comment.trim() ); } } private static void bindIndexAnnotation(Table table, AnnotationInstance indexAnnotation) { - String indexName = JandexHelper.getValueAsString( indexAnnotation, "appliesTo" ); - String[] columnNames = (String[]) JandexHelper.getValue( indexAnnotation, "columnNames" ); + String indexName = JandexHelper.getValue( indexAnnotation, "appliesTo", String.class ); + String[] columnNames = JandexHelper.getValue( indexAnnotation, "columnNames", String[].class ); if ( columnNames == null ) { LOG.noColumnsSpecifiedForIndex( indexName, table.toLoggableString() ); return; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java index 82a6d52453..9835403dc5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java @@ -57,33 +57,50 @@ public class TypeDefBinder { bind( metadata, typeDef ); } for ( AnnotationInstance typeDefs : jandex.getAnnotations( HibernateDotNames.TYPE_DEFS ) ) { - for ( AnnotationInstance typeDef : JandexHelper.getValueAsArray( typeDefs, "value" ) ) { + AnnotationInstance[] typeDefAnnotations = JandexHelper.getValue( + typeDefs, + "value", + AnnotationInstance[].class + ); + for ( AnnotationInstance typeDef : typeDefAnnotations ) { bind( metadata, typeDef ); } } } - private static void bind(MetadataImplementor metadata, AnnotationInstance typeDef) { - String name = JandexHelper.getValueAsString( typeDef, "name" ); - String defaultForType = JandexHelper.getValueAsString( typeDef, "defaultForType" ); - String typeClass = JandexHelper.getValueAsString( typeDef, "typeClass" ); + private static void bind(MetadataImplementor metadata, AnnotationInstance typeDefAnnotation) { + String name = JandexHelper.getValue( typeDefAnnotation, "name", String.class ); + String defaultForType = JandexHelper.getValue( typeDefAnnotation, "defaultForType", String.class ); + String typeClass = JandexHelper.getValue( typeDefAnnotation, "typeClass", String.class ); + boolean noName = StringHelper.isEmpty( name ); boolean noDefaultForType = defaultForType == null || defaultForType.equals( void.class.getName() ); + if ( noName && noDefaultForType ) { throw new AnnotationException( "Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass " + typeClass ); } - Map prms = new HashMap(); - for ( AnnotationInstance prm : JandexHelper.getValueAsArray( typeDef, "parameters" ) ) { - prms.put( JandexHelper.getValueAsString( prm, "name" ), JandexHelper.getValueAsString( prm, "value" ) ); + + Map parameterMaps = new HashMap(); + AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( + typeDefAnnotation, + "parameters", + AnnotationInstance[].class + ); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + parameterMaps.put( + JandexHelper.getValue( parameterAnnotation, "name", String.class ), + JandexHelper.getValue( parameterAnnotation, "value", String.class ) + ); } + if ( !noName ) { - bind( name, typeClass, prms, metadata ); + bind( name, typeClass, parameterMaps, metadata ); } if ( !noDefaultForType ) { - bind( defaultForType, typeClass, prms, metadata ); + bind( defaultForType, typeClass, parameterMaps, metadata ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/util/JandexHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/util/JandexHelper.java index 0f5d43cc97..4f0eb0b843 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/util/JandexHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/util/JandexHelper.java @@ -26,6 +26,7 @@ package org.hibernate.metamodel.source.annotations.util; 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; @@ -40,6 +41,7 @@ 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.AnnotationException; import org.hibernate.AssertionFailure; @@ -52,27 +54,89 @@ import org.hibernate.service.classloading.spi.ClassLoaderService; * @author Hardy Ferentschik */ public class JandexHelper { - private static final AnnotationInstance[] EMPTY_ANNOTATIONS_ARRAY = new AnnotationInstance[0]; private static final Map DEFAULT_VALUES_BY_ELEMENT = new HashMap(); - 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; + /** + * Retrieves a jandex annotation element value. If the value is {@code null}, the default value specified in the + * annotation class is retrieved instead. + *

+ * 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 #getValueAsEnum(AnnotationInstance, String, Class)}. + *

+ * + * @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: + *
    + *
  • Byte
  • + *
  • Short
  • + *
  • Integer
  • + *
  • Character
  • + *
  • Float
  • + *
  • Double
  • + *
  • Long
  • + *
  • Boolean
  • + *
  • String
  • + *
  • AnnotationInstance
  • + * + * @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 getValue(AnnotationInstance annotation, String element, Class 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)" + ); } + + // try getting the untyped value from Jandex + AnnotationValue annotationValue = annotation.value( element ); + try { - val = Index.class.getClassLoader().loadClass( name ).getMethod( element ).getDefaultValue(); - DEFAULT_VALUES_BY_ELEMENT.put( fqElement, val ); - return val == null ? null : val; + if ( annotationValue != null ) { + return explicitAnnotationParameter( annotationValue, type ); + } + else { + return defaultAnnotationParameter( getDefaultValue( annotation, element ), type ); + } } - catch ( RuntimeException error ) { - throw error; + 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() + ) + ); } - catch ( Exception error ) { - throw new AnnotationException( error ); + } + + /** + * Retrieves a jandex annotation element value, converting it to the supplied enumerated type. If the value is + * null, the default value specified in the annotation class is retrieved instead. + * + * @param 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 null, else the default value if + * not null, else null. + * + * @see #getValue(AnnotationInstance, String, Class) + */ + @SuppressWarnings("unchecked") + public static > T getValueAsEnum(AnnotationInstance annotation, String element, Class type) { + AnnotationValue val = annotation.value( element ); + if ( val == null ) { + return (T) getDefaultValue( annotation, element ); } + return Enum.valueOf( type, val.asEnum() ); } /** @@ -149,98 +213,6 @@ public class JandexHelper { } } - /** - * Retrieves a jandex annotation element value. If the value is null, the default value specified in the - * annotation class is retrieved instead. Note, {@link #getValueAsEnum(AnnotationInstance, String, Class)} must be - * called to retrieve an enumerated value, and {@link #getValueAsArray(AnnotationInstance, String)} must be called to retrieve - * an object array (other than a String array). - * - * @param annotation the annotation containing the element with the supplied name - * @param element the name of the element value to be retrieve - * - * @return the value if not null, else the default value if not - * null, else null. - */ - public static Object getValue(AnnotationInstance annotation, String element) { - AnnotationValue val = annotation.value( element ); - if ( val == null ) { - return getDefaultValue( annotation, element ); - } - return val.asNested(); - } - - /** - * Retrieves a jandex annotation element array. Note, {@link #getValue(AnnotationInstance, String)} may be - * called to retrieve a String array (or a non-array value). - * - * @param annotation the jandex annotation containing the element with the supplied name - * @param element the name of the element array - * - * @return the element array if not null, else an empty array - */ - public static AnnotationInstance[] getValueAsArray(AnnotationInstance annotation, String element) { - AnnotationValue val = annotation.value( element ); - return val == null ? EMPTY_ANNOTATIONS_ARRAY : val.asNestedArray(); - } - - /** - * Retrieves a jandex annotation element value, converting it to the supplied enumerated type. If the value is - * null, the default value specified in the annotation class is retrieved instead. - * - * @param 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 null, else the default value if - * not null, else null. - * - * @see #getValue(AnnotationInstance, String) - */ - public static > T getValueAsEnum(AnnotationInstance annotation, String element, Class type) { - AnnotationValue val = annotation.value( element ); - if ( val == null ) { - return (T) getDefaultValue( annotation, element ); - } - return Enum.valueOf( type, val.asEnum() ); - } - - /** - * Retrieves a jandex annotation element value as an Integer. If the value is null, the default value specified in - * the annotation class is retrieved instead. - * - * @param annotation the annotation containing the element with the supplied name - * @param element the name of the element value to be retrieve - * - * @return the value converted to an int if the value is not null, else the default value if not - * null, else 0. - */ - public static int getValueAsInt(AnnotationInstance annotation, String element) { - AnnotationValue val = annotation.value( element ); - if ( val == null ) { - return (Integer) getDefaultValue( annotation, element ); - } - return val.asInt(); - } - - /** - * Retrieves a jandex annotation element value as a String. If the value is null, the default value specified in - * the annotation class is retrieved instead. - * - * @param annotation the annotation containing the element with the supplied name - * @param element the name of the element value to be retrieve - * - * @return the value converted to a String if the value is not null, else the default value if not - * null, else null. - */ - public static String getValueAsString(AnnotationInstance annotation, String element) { - AnnotationValue val = annotation.value( element ); - if ( val == null ) { - return (String) getDefaultValue( annotation, element ); - } - return val.asString(); - } - /** * Creates a jandex index for the specified classes * @@ -334,4 +306,59 @@ public class JandexHelper { private JandexHelper() { } + + 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 AnnotationException( error ); + } + } + + private static T defaultAnnotationParameter(Object defaultValue, Class 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 explicitAnnotationParameter(AnnotationValue annotationValue, Class 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 ); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java index ba455ec27f..bd9fa9885d 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java @@ -23,26 +23,26 @@ */ package org.hibernate.metamodel.source.annotations.util; -import static org.hamcrest.core.Is.is; - -import static org.junit.Assert.assertThat; - import java.util.List; import java.util.Map; +import javax.persistence.AttributeOverride; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.LockModeType; import javax.persistence.NamedQuery; -import javax.persistence.SequenceGenerator; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.hibernate.AssertionFailure; +import org.hibernate.annotations.NamedNativeQuery; +import org.hibernate.metamodel.source.annotations.HibernateDotNames; import org.hibernate.metamodel.source.annotations.JPADotNames; import org.hibernate.service.ServiceRegistryBuilder; import org.hibernate.service.classloading.spi.ClassLoaderService; @@ -50,8 +50,12 @@ import org.hibernate.service.internal.BasicServiceRegistryImpl; import org.hibernate.testing.junit4.BaseUnitTestCase; import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; /** + * Tests for the helper class {@link JandexHelper}. + * * @author Hardy Ferentschik */ public class JandexHelperTest extends BaseUnitTestCase { @@ -75,7 +79,6 @@ public class JandexHelperTest extends BaseUnitTestCase { @Column @Basic private String bar; - private String fubar; } Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); @@ -98,47 +101,122 @@ public class JandexHelperTest extends BaseUnitTestCase { } @Test - public void shouldRetrieveDefaultOfUnspecifiedAnnotationElement() { - - @NamedQuery(name="foo", query="bar") - @SequenceGenerator(name="fu") + public void testGettingNestedAnnotation() { + @AttributeOverride(name = "foo", column = @Column(name = "FOO")) class Foo { } - Index index = JandexHelper.indexForClass(classLoaderService, Foo.class); - for (AnnotationInstance query : index.getAnnotations( JPADotNames.NAMED_QUERY)) { - assertThat(JandexHelper.getValueAsEnum(query, "lockMode", LockModeType.class), is(LockModeType.NONE)); - } - for (AnnotationInstance generator : index.getAnnotations( JPADotNames.SEQUENCE_GENERATOR)) { - assertThat(JandexHelper.getValueAsInt(generator, "allocationSize"), is(50)); - } + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + + // try to retrieve the name + String name = JandexHelper.getValue( annotationInstance, "name", String.class ); + assertEquals( "Wrong nested annotation", "foo", name ); + + // try to retrieve the nested column annotation instance + AnnotationInstance columnAnnotationInstance = JandexHelper.getValue( + annotationInstance, + "column", + AnnotationInstance.class + ); + assertNotNull( columnAnnotationInstance ); + assertEquals( + "Wrong nested annotation", + "javax.persistence.Column", + columnAnnotationInstance.name().toString() + ); } - @Test - public void shouldRetrieveValueOfAnnotationElement() { + @Test(expected = AssertionFailure.class) + public void testTryingToRetrieveWrongType() { + @AttributeOverride(name = "foo", column = @Column(name = "FOO")) + class Foo { + } - @NamedQuery(name="foo", query="bar") - class Foo { - } + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - Index index = JandexHelper.indexForClass(classLoaderService, Foo.class); - for (AnnotationInstance query : index.getAnnotations( JPADotNames.NAMED_QUERY)) { - assertThat(JandexHelper.getValueAsString(query, "name"), is("foo")); - } - } + JandexHelper.getValue( annotationInstance, "name", Float.class ); + } - @Test - public void shouldRetrieveValueOfEnumeratedAnnotationElement() { + @Test + public void testRetrieveDefaultEnumElement() { + @NamedQuery(name = "foo", query = "fubar") + class Foo { + } - @NamedQuery(name="foo", query="bar", lockMode=LockModeType.OPTIMISTIC) - class Foo { - } + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - Index index = JandexHelper.indexForClass(classLoaderService, Foo.class); - for (AnnotationInstance query : index.getAnnotations( JPADotNames.NAMED_QUERY)) { - assertThat(JandexHelper.getValueAsEnum(query, "lockMode", LockModeType.class), is(LockModeType.OPTIMISTIC)); - } - } + LockModeType lockMode = JandexHelper.getValueAsEnum( annotationInstance, "lockMode", LockModeType.class ); + assertEquals( "Wrong lock mode", LockModeType.NONE, lockMode ); + } + + @Test + public void testRetrieveExplicitEnumElement() { + @NamedQuery(name = "foo", query = "bar", lockMode = LockModeType.OPTIMISTIC) + class Foo { + } + + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + + LockModeType lockMode = JandexHelper.getValueAsEnum( annotationInstance, "lockMode", LockModeType.class ); + assertEquals( "Wrong lock mode", LockModeType.OPTIMISTIC, lockMode ); + } + + @Test + public void testRetrieveStringArray() { + class Foo { + @org.hibernate.annotations.Index(name = "index", columnNames = { "a", "b", "c" }) + private String foo; + } + + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( HibernateDotNames.INDEX ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + + String[] columnNames = JandexHelper.getValue( annotationInstance, "columnNames", String[].class ); + Assert.assertTrue( columnNames.length == 3 ); + } + + @Test(expected = AssertionFailure.class) + public void testRetrieveClassParameterAsClass() { + @NamedNativeQuery(name = "foo", query = "bar", resultClass = Foo.class) + class Foo { + } + + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + + JandexHelper.getValue( annotationInstance, "resultClass", Class.class ); + } + + @Test + public void testRetrieveClassParameterAsString() { + @NamedNativeQuery(name = "foo", query = "bar", resultClass = Foo.class) + class Foo { + } + + Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + List annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + + String fqcn = JandexHelper.getValue( annotationInstance, "resultClass", String.class ); + assertEquals( "Wrong class names", Foo.class.getName(), fqcn ); + } }