HHH-6172 Extracting initial attributes for ManyToOne

This commit is contained in:
Hardy Ferentschik 2011-05-24 12:01:03 +02:00
parent 49e75c83ce
commit 3960b0d8ea
7 changed files with 157 additions and 57 deletions

View File

@ -22,18 +22,20 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.annotations;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Action to do when an element is not found on a association whiel beeing expected
* Action to do when an element is not found on a association.
*
* @author Emmanuel Bernard
*/
@Target({METHOD, FIELD})
@Target( { METHOD, FIELD })
@Retention(RUNTIME)
public @interface NotFound {
NotFoundAction action() default NotFoundAction.EXCEPTION;

View File

@ -27,13 +27,20 @@ import java.util.List;
import java.util.Map;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.DotName;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
/**
* @author Hardy Ferentschik
*/
public class AssociationAttribute extends SimpleAttribute {
private final AssociationType associationType;
private final boolean ignoreNotFound;
private final String referencedEntityType;
public static AssociationAttribute createAssociationAttribute(String name, String type, AssociationType associationType, Map<DotName, List<AnnotationInstance>> annotations) {
return new AssociationAttribute( name, type, associationType, annotations );
@ -42,11 +49,56 @@ public class AssociationAttribute extends SimpleAttribute {
private AssociationAttribute(String name, String type, AssociationType associationType, Map<DotName, List<AnnotationInstance>> annotations) {
super( name, type, annotations, false );
this.associationType = associationType;
this.ignoreNotFound = ignoreNotFound();
AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation(
annotations,
associationType.getAnnotationDotName()
);
referencedEntityType = determineReferencedEntityType( associationAnnotation );
}
public boolean isIgnoreNotFound() {
return ignoreNotFound;
}
public String getReferencedEntityType() {
return referencedEntityType;
}
public AssociationType getAssociationType() {
return associationType;
}
private boolean ignoreNotFound() {
NotFoundAction action = NotFoundAction.EXCEPTION;
AnnotationInstance notFoundAnnotation = getIfExists( HibernateDotNames.NOT_FOUND );
if ( notFoundAnnotation != null ) {
AnnotationValue actionValue = notFoundAnnotation.value( "action" );
if ( actionValue != null ) {
action = Enum.valueOf( NotFoundAction.class, actionValue.asEnum() );
}
}
return NotFoundAction.IGNORE.equals( action );
}
private String determineReferencedEntityType(AnnotationInstance associationAnnotation) {
String targetTypeName = getType();
AnnotationInstance targetAnnotation = getIfExists( HibernateDotNames.TARGET );
if ( targetAnnotation != null ) {
targetTypeName = targetAnnotation.value().asClass().name().toString();
}
AnnotationValue targetEntityValue = associationAnnotation.value( "targetEntity" );
if ( targetEntityValue != null ) {
targetTypeName = targetEntityValue.asClass().name().toString();
}
return targetTypeName;
}
}

View File

@ -23,13 +23,27 @@
*/
package org.hibernate.metamodel.source.annotations.entity;
import org.jboss.jandex.DotName;
import org.hibernate.metamodel.source.annotations.JPADotNames;
/**
* @author Hardy Ferentschik
*/
public enum AssociationType {
NO_ASSOCIATION,
ONE_TO_ONE,
ONE_TO_MANY,
MANY_TO_ONE,
MANY_TO_MANY
NO_ASSOCIATION( null ),
ONE_TO_ONE( JPADotNames.ONE_TO_ONE ),
ONE_TO_MANY( JPADotNames.ONE_TO_MANY ),
MANY_TO_ONE( JPADotNames.MANY_TO_ONE ),
MANY_TO_MANY( JPADotNames.MANY_TO_MANY );
private final DotName annotationDotName;
AssociationType(DotName annotationDotName) {
this.annotationDotName = annotationDotName;
}
public DotName getAnnotationDotName() {
return annotationDotName;
}
}

View File

@ -39,7 +39,9 @@ import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.metamodel.binding.Caching;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.binding.state.ManyToOneAttributeBindingState;
import org.hibernate.metamodel.binding.state.SimpleAttributeBindingState;
import org.hibernate.metamodel.domain.Entity;
import org.hibernate.metamodel.domain.Hierarchical;
@ -49,7 +51,9 @@ import org.hibernate.metamodel.source.annotations.HibernateDotNames;
import org.hibernate.metamodel.source.annotations.JPADotNames;
import org.hibernate.metamodel.source.annotations.entity.state.binding.AttributeBindingStateImpl;
import org.hibernate.metamodel.source.annotations.entity.state.binding.DiscriminatorBindingStateImpl;
import org.hibernate.metamodel.source.annotations.entity.state.binding.ManyToOneBindingStateImpl;
import org.hibernate.metamodel.source.annotations.entity.state.relational.ColumnRelationalStateImpl;
import org.hibernate.metamodel.source.annotations.entity.state.relational.ManyToOneRelationalStateImpl;
import org.hibernate.metamodel.source.annotations.entity.state.relational.TupleRelationalStateImpl;
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.source.spi.MetadataImplementor;
@ -319,7 +323,7 @@ public class EntityBinder {
private void bindAttributes(EntityBinding entityBinding) {
for ( MappedAttribute mappedAttribute : configuredClass.getMappedAttributes() ) {
if ( mappedAttribute instanceof AssociationAttribute ) {
// todo
bindAssociationAttribute( entityBinding, (AssociationAttribute) mappedAttribute );
}
else {
bindSingleMappedAttribute( entityBinding, (SimpleAttribute) mappedAttribute );
@ -327,39 +331,64 @@ public class EntityBinder {
}
}
private void bindSingleMappedAttribute(EntityBinding entityBinding, SimpleAttribute mappedAttribute) {
if ( mappedAttribute.isId() ) {
private void bindAssociationAttribute(EntityBinding entityBinding, AssociationAttribute associationAttribute) {
switch ( associationAttribute.getAssociationType() ) {
case MANY_TO_ONE: {
entityBinding.getEntity().getOrCreateSingularAttribute( associationAttribute.getName() );
ManyToOneAttributeBinding manyToOneAttributeBinding = entityBinding.makeManyToOneAttributeBinding(
associationAttribute.getName()
);
ManyToOneAttributeBindingState bindingState = new ManyToOneBindingStateImpl( associationAttribute );
manyToOneAttributeBinding.initialize( bindingState );
ManyToOneRelationalStateImpl relationalState = new ManyToOneRelationalStateImpl();
if ( configuredClass.hasOwnTable() ) {
ColumnRelationalStateImpl columnRelationsState = new ColumnRelationalStateImpl(
associationAttribute, meta
);
relationalState.addValueState( columnRelationsState );
}
manyToOneAttributeBinding.initialize( relationalState );
break;
}
default: {
// todo
}
}
}
private void bindSingleMappedAttribute(EntityBinding entityBinding, SimpleAttribute simpleAttribute) {
if ( simpleAttribute.isId() ) {
return;
}
String attributeName = mappedAttribute.getName();
String attributeName = simpleAttribute.getName();
entityBinding.getEntity().getOrCreateSingularAttribute( attributeName );
SimpleAttributeBinding attributeBinding;
SimpleAttributeBindingState bindingState;
if ( mappedAttribute.isDiscriminator() ) {
if ( simpleAttribute.isDiscriminator() ) {
attributeBinding = entityBinding.makeEntityDiscriminator( attributeName ).getValueBinding();
bindingState = new DiscriminatorBindingStateImpl( mappedAttribute );
bindingState = new DiscriminatorBindingStateImpl( simpleAttribute );
}
else if ( mappedAttribute.isVersioned() ) {
else if ( simpleAttribute.isVersioned() ) {
attributeBinding = entityBinding.makeVersionBinding( attributeName );
bindingState = new AttributeBindingStateImpl( mappedAttribute );
bindingState = new AttributeBindingStateImpl( simpleAttribute );
}
else {
attributeBinding = entityBinding.makeSimpleAttributeBinding( attributeName );
bindingState = new AttributeBindingStateImpl( mappedAttribute );
bindingState = new AttributeBindingStateImpl( simpleAttribute );
}
attributeBinding.initialize( bindingState );
if ( configuredClass.hasOwnTable() ) {
ColumnRelationalStateImpl columnRelationsState = new ColumnRelationalStateImpl(
mappedAttribute, meta
simpleAttribute, meta
);
TupleRelationalStateImpl relationalState = new TupleRelationalStateImpl();
relationalState.addValueState( columnRelationsState );
// TODO: if this really just binds a column, then it can be changed to
// attributeBinding.initialize( columnRelationsState );
attributeBinding.initialize( relationalState );
}
}

View File

@ -46,9 +46,9 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
private final Map<DotName, List<AnnotationInstance>> annotations;
/**
* The property type as string.
* The property name.
*/
private final String type;
private final String name;
/**
* Optional type parameters for custom types.
@ -56,9 +56,9 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
private final Map<String, String> typeParameters;
/**
* The property name.
* The property type as string.
*/
private final String name;
private final String type;
MappedAttribute(String name, String type, Map<DotName, List<AnnotationInstance>> annotations) {
this.annotations = annotations;
@ -101,6 +101,22 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
}
}
@Override
public int compareTo(MappedAttribute mappedProperty) {
return name.compareTo( mappedProperty.getName() );
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "MappedAttribute" );
sb.append( "{type='" ).append( type ).append( '\'' );
sb.append( ", typeParameters=" ).append( typeParameters );
sb.append( ", name='" ).append( name ).append( '\'' );
sb.append( '}' );
return sb.toString();
}
/**
* We need to check whether the is an explicit type specified via {@link org.hibernate.annotations.Type}.
*
@ -129,22 +145,6 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
return typeAnnotation.value( "type" ).asString();
}
@Override
public int compareTo(MappedAttribute mappedProperty) {
return name.compareTo( mappedProperty.getName() );
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "MappedAttribute" );
sb.append( "{type='" ).append( type ).append( '\'' );
sb.append( ", typeParameters=" ).append( typeParameters );
sb.append( ", name='" ).append( name ).append( '\'' );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -30,28 +30,41 @@ import org.hibernate.metamodel.source.annotations.entity.AssociationAttribute;
* @author Hardy Ferentschik
*/
public class ManyToOneBindingStateImpl extends AttributeBindingStateImpl implements ManyToOneAttributeBindingState {
private final AssociationAttribute associationAttribute;
public ManyToOneBindingStateImpl(AssociationAttribute associationAttribute) {
super( associationAttribute );
this.associationAttribute = associationAttribute;
}
@Override
public boolean isUnwrapProxy() {
return false; //To change body of implemented methods use File | Settings | File Templates.
public boolean isLazy() {
return associationAttribute.isLazy();
}
@Override
public String getReferencedAttributeName() {
public String getCascade() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getReferencedEntityName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
return associationAttribute.getReferencedEntityType();
}
@Override
public boolean ignoreNotFound() {
return false; //To change body of implemented methods use File | Settings | File Templates.
return associationAttribute.isIgnoreNotFound();
}
@Override
public boolean isUnwrapProxy() {
return false;
}
@Override
public String getReferencedAttributeName() {
return null;
}
}

View File

@ -23,11 +23,8 @@
*/
package org.hibernate.metamodel.binding;
import org.junit.Test;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.source.internal.MetadataImpl;
import org.hibernate.testing.FailureExpected;
/**
* Basic tests of annotation based binding code
@ -35,16 +32,9 @@ import org.hibernate.testing.FailureExpected;
* @author Hardy Ferentschik
*/
public class BasicAnnotationBindingTests extends AbstractBasicBindingTests {
@FailureExpected(jiraKey = "HHH-6172", message = "Work in progress")
@Test
public void testEntityWithManyToOneMapping() {
super.testEntityWithManyToOneMapping();
}
public MetadataImpl addSourcesForSimpleEntityBinding(MetadataSources sources) {
sources.addAnnotatedClass( SimpleEntity.class );
return (MetadataImpl) sources.buildMetadata();
}
public MetadataImpl addSourcesForSimpleVersionedEntityBinding(MetadataSources sources) {