HHH-7628: Modified ConfiguredClass to also process @AccessType annotations
This commit is contained in:
parent
07405e0f00
commit
78060d8eac
|
@ -1596,18 +1596,33 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
)
|
||||
void tooManyInExpressions(String dialectName, int limit, String paramName, int size);
|
||||
|
||||
|
||||
// moved from hibernate-entitymanager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 )
|
||||
@Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 448 )
|
||||
void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName,
|
||||
String attributeName,
|
||||
String attributeJavaType,
|
||||
String metamodelFieldJavaType );
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 )
|
||||
@Message( value = "Unable to locate static metamodel field : %s#%s", id = 449 )
|
||||
void unableToLocateStaticMetamodelField( String metamodelClassName,
|
||||
String attributeName );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||
"@Access has to be placed on the property (getter)", id = 450)
|
||||
String accessTypeOverrideShouldBeAnnotatedOnProperty( String className );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||
"@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " +
|
||||
"Using AccessType.FIELD on the property has no effect", id = 451)
|
||||
String accessTypeOverrideShouldBeProperty( String className );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||
"@Access has to be placed on the field ", id = 452)
|
||||
String accessTypeOverrideShouldBeAnnotatedOnField( String className );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||
"@Access has to be placed on the field with an access type of AccessType.FIELD. " +
|
||||
"Using AccessType.PROPERTY on the field has no effect", id = 453)
|
||||
String accessTypeOverrideShouldBeField( String className );
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
|
@ -37,23 +36,14 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.members.HierarchicType;
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
import org.jboss.logging.Logger;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
|
@ -66,6 +56,17 @@ import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
|||
import org.hibernate.metamodel.internal.source.annotations.util.ReflectionHelper;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.members.HierarchicType;
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
|
||||
/**
|
||||
* Base class for a configured entity, mapped super class or embeddable
|
||||
|
@ -73,7 +74,7 @@ import org.hibernate.metamodel.spi.source.MappingException;
|
|||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ConfiguredClass {
|
||||
public static final Logger LOG = Logger.getLogger( ConfiguredClass.class.getName() );
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AssertionFailure.class.getName());
|
||||
|
||||
/**
|
||||
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
||||
|
@ -233,8 +234,13 @@ public class ConfiguredClass {
|
|||
AccessType accessType = defaultAccessType;
|
||||
|
||||
AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ACCESS, ClassInfo.class );
|
||||
if ( accessAnnotation != null && accessAnnotation.target().getClass().equals( ClassInfo.class ) ) {
|
||||
if ( accessAnnotation != null ) {
|
||||
accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class );
|
||||
} else {
|
||||
accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, HibernateDotNames.ACCESS_TYPE, ClassInfo.class );
|
||||
if ( accessAnnotation != null ) {
|
||||
accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() );
|
||||
}
|
||||
}
|
||||
|
||||
return accessType;
|
||||
|
@ -321,9 +327,15 @@ public class ConfiguredClass {
|
|||
Set<String> explicitAccessPropertyNames = new HashSet<String>();
|
||||
|
||||
List<AnnotationInstance> accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS );
|
||||
List<AnnotationInstance> hibernateAccessAnnotations = classInfo.annotations().get( HibernateDotNames.ACCESS_TYPE );
|
||||
if ( accessAnnotations == null ) {
|
||||
accessAnnotations = hibernateAccessAnnotations;
|
||||
if ( accessAnnotations == null ) {
|
||||
return explicitAccessPropertyNames;
|
||||
}
|
||||
} else if ( hibernateAccessAnnotations != null ) {
|
||||
accessAnnotations.addAll( hibernateAccessAnnotations );
|
||||
}
|
||||
|
||||
// iterate over all @Access annotations defined on the current class
|
||||
for ( AnnotationInstance accessAnnotation : accessAnnotations ) {
|
||||
|
@ -334,18 +346,19 @@ public class ConfiguredClass {
|
|||
continue;
|
||||
}
|
||||
|
||||
AccessType accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class );
|
||||
|
||||
if ( !isExplicitAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ) ) {
|
||||
continue;
|
||||
AccessType accessType;
|
||||
if ( JPADotNames.ACCESS.equals( accessAnnotation.name() ) ) {
|
||||
accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class );
|
||||
checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType );
|
||||
} else {
|
||||
accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() );
|
||||
}
|
||||
|
||||
// the placement is correct, get the member
|
||||
Member member;
|
||||
if ( annotationTarget instanceof MethodInfo ) {
|
||||
Method m;
|
||||
try {
|
||||
m = clazz.getMethod( ( ( MethodInfo ) annotationTarget ).name() );
|
||||
member = clazz.getMethod( ( ( MethodInfo ) annotationTarget ).name() );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
throw new HibernateException(
|
||||
|
@ -354,13 +367,10 @@ public class ConfiguredClass {
|
|||
+ " of class " + clazz.getName()
|
||||
);
|
||||
}
|
||||
member = m;
|
||||
accessType = AccessType.PROPERTY;
|
||||
}
|
||||
else {
|
||||
Field f;
|
||||
try {
|
||||
f = clazz.getField( ( ( FieldInfo ) annotationTarget ).name() );
|
||||
member = clazz.getField( ( ( FieldInfo ) annotationTarget ).name() );
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
throw new HibernateException(
|
||||
|
@ -369,8 +379,6 @@ public class ConfiguredClass {
|
|||
+ " of class " + clazz.getName()
|
||||
);
|
||||
}
|
||||
member = f;
|
||||
accessType = AccessType.FIELD;
|
||||
}
|
||||
if ( ReflectionHelper.isProperty( member ) ) {
|
||||
createMappedAttribute( member, resolvedMembers, accessType );
|
||||
|
@ -380,26 +388,20 @@ public class ConfiguredClass {
|
|||
return explicitAccessPropertyNames;
|
||||
}
|
||||
|
||||
private boolean isExplicitAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) {
|
||||
private void checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) {
|
||||
// when the access type of the class is FIELD
|
||||
// overriding access annotations must be placed on properties AND have the access type PROPERTY
|
||||
if ( AccessType.FIELD.equals( classAccessType ) ) {
|
||||
if ( !MethodInfo.class.isInstance( annotationTarget ) ) {
|
||||
LOG.tracef(
|
||||
"The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||
"@Access has to be placed on the property (getter)", classInfo.name().toString()
|
||||
);
|
||||
return false;
|
||||
String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnProperty( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
|
||||
if ( !AccessType.PROPERTY.equals( accessType ) ) {
|
||||
LOG.tracef(
|
||||
"The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||
"@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " +
|
||||
"Using AccessType.FIELD on the property has no effect",
|
||||
classInfo.name().toString()
|
||||
);
|
||||
return false;
|
||||
String msg = LOG.accessTypeOverrideShouldBeProperty( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,24 +409,17 @@ public class ConfiguredClass {
|
|||
// overriding access annotations must be placed on fields and have the access type FIELD
|
||||
if ( AccessType.PROPERTY.equals( classAccessType ) ) {
|
||||
if ( !FieldInfo.class.isInstance( annotationTarget ) ) {
|
||||
LOG.tracef(
|
||||
"The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||
"@Access has to be placed on the field ", classInfo.name().toString()
|
||||
);
|
||||
return false;
|
||||
String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnField( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
|
||||
if ( !AccessType.FIELD.equals( accessType ) ) {
|
||||
LOG.tracef(
|
||||
"The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||
"@Access has to be placed on the field with an access type of AccessType.FIELD. " +
|
||||
"Using AccessType.PROPERTY on the field has no effect",
|
||||
classInfo.name().toString()
|
||||
);
|
||||
return false;
|
||||
String msg = LOG.accessTypeOverrideShouldBeField( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createMappedAttribute(Member member, ResolvedTypeWithMembers resolvedType, AccessType accessType) {
|
||||
|
@ -476,6 +471,7 @@ public class ConfiguredClass {
|
|||
);
|
||||
idAttributeMap.put( attributeName, attribute );
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
case EMBEDDED: {
|
||||
final AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
|
@ -520,7 +516,7 @@ public class ConfiguredClass {
|
|||
associationAttributeMap.put( attributeName, attribute );
|
||||
break;
|
||||
}
|
||||
|
||||
case MANY_TO_ANY: {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -722,29 +718,6 @@ public class ConfiguredClass {
|
|||
return prefix;
|
||||
}
|
||||
|
||||
private List<AnnotationInstance> findAssociationOverrides() {
|
||||
List<AnnotationInstance> associationOverrideList = new ArrayList<AnnotationInstance>();
|
||||
|
||||
AnnotationInstance associationOverrideAnnotation = JandexHelper.getSingleAnnotation(
|
||||
classInfo,
|
||||
JPADotNames.ASSOCIATION_OVERRIDE
|
||||
);
|
||||
if ( associationOverrideAnnotation != null ) {
|
||||
associationOverrideList.add( associationOverrideAnnotation );
|
||||
}
|
||||
|
||||
AnnotationInstance associationOverridesAnnotation = JandexHelper.getSingleAnnotation(
|
||||
classInfo,
|
||||
JPADotNames.ASSOCIATION_OVERRIDES
|
||||
);
|
||||
if ( associationOverrideAnnotation != null ) {
|
||||
AnnotationInstance[] attributeOverride = associationOverridesAnnotation.value().asNestedArray();
|
||||
Collections.addAll( associationOverrideList, attributeOverride );
|
||||
}
|
||||
|
||||
return associationOverrideList;
|
||||
}
|
||||
|
||||
private String determineCustomTuplizer() {
|
||||
final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation(
|
||||
classInfo, HibernateDotNames.TUPLIZERS
|
||||
|
|
|
@ -38,9 +38,10 @@ import static org.junit.Assert.assertNull;
|
|||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class AccessTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testSuperclassOverriding() throws Exception {
|
||||
Furniture fur = new Furniture();
|
||||
fur.setColor( "Black" );
|
||||
|
@ -61,6 +62,7 @@ public class AccessTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testSuperclassNonOverriding() throws Exception {
|
||||
Furniture fur = new Furniture();
|
||||
fur.setGod( "Buddha" );
|
||||
|
@ -76,7 +78,9 @@ public class AccessTest extends BaseCoreFunctionalTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testPropertyOverriding() throws Exception {
|
||||
Furniture fur = new Furniture();
|
||||
fur.weight = 3;
|
||||
|
@ -92,7 +96,9 @@ public class AccessTest extends BaseCoreFunctionalTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testNonOverridenSubclass() throws Exception {
|
||||
Chair chair = new Chair();
|
||||
chair.setPillow( "Blue" );
|
||||
|
@ -108,7 +114,9 @@ public class AccessTest extends BaseCoreFunctionalTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testOverridenSubclass() throws Exception {
|
||||
BigBed bed = new BigBed();
|
||||
bed.size = 5;
|
||||
|
@ -126,6 +134,7 @@ public class AccessTest extends BaseCoreFunctionalTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldsOverriding() throws Exception {
|
||||
Gardenshed gs = new Gardenshed();
|
||||
|
@ -143,6 +152,7 @@ public class AccessTest extends BaseCoreFunctionalTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
|
|
|
@ -50,7 +50,6 @@ public class EagerKeyManyToOneTest extends BaseCoreFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-4147" )
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testLoadEntityWithEagerFetchingToKeyManyToOneReferenceBackToSelf() {
|
||||
// based on the core testsuite test of same name in org.hibernate.test.keymanytoone.bidir.component.EagerKeyManyToOneTest
|
||||
// meant to test against regression relating to http://opensource.atlassian.com/projects/hibernate/browse/HHH-2277
|
||||
|
|
Loading…
Reference in New Issue