From e875bb6004357e63c94f1f186c71da1685502e8a Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Mon, 1 Aug 2011 18:08:49 +0200 Subject: [PATCH] HHH-6393 First cut of attribute overrides for embeddables --- .../attribute/ColumnSourceImpl.java | 31 ++++--- .../attribute/ColumnValuesSourceImpl.java | 6 +- .../attribute/SimpleIdentifierSourceImpl.java | 6 +- .../SingularAttributeSourceImpl.java | 9 +- .../entity/ComponentAttributeSourceImpl.java | 20 ++++- .../annotations/entity/EntitySourceImpl.java | 2 +- .../entity/RootEntitySourceImpl.java | 7 +- .../entity/EmbeddableBindingTest.java | 84 ++++++++++++++----- 8 files changed, 118 insertions(+), 47 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java index d773d46fb8..56b124aa8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java @@ -30,25 +30,30 @@ import org.hibernate.internal.util.StringHelper; */ public class ColumnSourceImpl extends ColumnValuesSourceImpl { private final BasicAttribute attribute; - private final String name; - ColumnSourceImpl(BasicAttribute attribute) { + private final String name; + + ColumnSourceImpl(BasicAttribute attribute, AttributeOverride attributeOverride) { super( attribute.getColumnValues() ); + if(attributeOverride != null) { + setOverrideColumnValues( attributeOverride.getColumnValues() ); + } this.attribute = attribute; - this.name = resolveColumnName(); + this.name = resolveColumnName(); + } + + protected String resolveColumnName() { + if ( StringHelper.isEmpty( super.getName() ) ) { + //no @Column defined. + return attribute.getContext().getNamingStrategy().propertyToColumnName( attribute.getName() ); + } + else { + return super.getName(); + } } - protected String resolveColumnName() { - if ( StringHelper.isEmpty( super.getName() ) ) { - //no @Column defined. - return attribute.getContext().getNamingStrategy().propertyToColumnName( attribute.getName() ); - } - else { - return super.getName(); - } - } @Override public String getName() { - return name; + return name; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java index 8156a27f1a..16480cf0c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java @@ -31,12 +31,16 @@ import org.hibernate.metamodel.source.binder.ColumnSource; * @author Steve Ebersole */ public class ColumnValuesSourceImpl implements ColumnSource { - private final ColumnValues columnValues; + private ColumnValues columnValues; public ColumnValuesSourceImpl(ColumnValues columnValues) { this.columnValues = columnValues; } + void setOverrideColumnValues(ColumnValues columnValues) { + this.columnValues = columnValues; + } + @Override public String getName() { return columnValues.getName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java index cf4cc77d2e..e6ae635ea9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java @@ -23,6 +23,8 @@ */ package org.hibernate.metamodel.source.annotations.attribute; +import java.util.Map; + import org.hibernate.AssertionFailure; import org.hibernate.metamodel.binding.IdGenerator; import org.hibernate.metamodel.source.binder.SimpleIdentifierSource; @@ -33,8 +35,9 @@ import org.hibernate.metamodel.source.binder.SingularAttributeSource; */ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { private final BasicAttribute attribute; + private final Map attributeOverrideMap; - public SimpleIdentifierSourceImpl(BasicAttribute attribute) { + public SimpleIdentifierSourceImpl(BasicAttribute attribute, Map attributeOverrideMap) { if ( !attribute.isId() ) { throw new AssertionFailure( String.format( @@ -44,6 +47,7 @@ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { ); } this.attribute = attribute; + this.attributeOverrideMap = attributeOverrideMap; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java index 076b4e935a..048df6971e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java @@ -26,7 +26,6 @@ package org.hibernate.metamodel.source.annotations.attribute; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; @@ -40,9 +39,15 @@ import org.hibernate.metamodel.source.binder.SingularAttributeSource; */ public class SingularAttributeSourceImpl implements SingularAttributeSource { private final BasicAttribute attribute; + private final AttributeOverride attributeOverride; public SingularAttributeSourceImpl(BasicAttribute attribute) { + this(attribute, null); + } + + public SingularAttributeSourceImpl(BasicAttribute attribute, AttributeOverride attributeOverride) { this.attribute = attribute; + this.attributeOverride = attributeOverride; } @Override @@ -88,7 +93,7 @@ public class SingularAttributeSourceImpl implements SingularAttributeSource { @Override public List relationalValueSources() { List valueSources = new ArrayList(); - valueSources.add( new ColumnSourceImpl( attribute ) ); + valueSources.add( new ColumnSourceImpl( attribute, attributeOverride ) ); return valueSources; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java index c0b31bbf18..af0944b1d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java @@ -26,6 +26,7 @@ package org.hibernate.metamodel.source.annotations.entity; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import org.jboss.jandex.AnnotationInstance; @@ -34,6 +35,7 @@ import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.source.LocalBindingContext; import org.hibernate.metamodel.source.annotations.JandexHelper; import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; import org.hibernate.metamodel.source.annotations.attribute.ToOneAttributeSourceImpl; @@ -53,11 +55,13 @@ import org.hibernate.metamodel.source.binder.SingularAttributeNature; public class ComponentAttributeSourceImpl implements ComponentAttributeSource { private final EmbeddableClass embeddableClass; private final Value> classReference; + private final Map attributeOverrides; private final String path; - public ComponentAttributeSourceImpl(EmbeddableClass embeddableClass) { + public ComponentAttributeSourceImpl(EmbeddableClass embeddableClass, Map attributeOverrides) { this.embeddableClass = embeddableClass; this.classReference = new Value>( embeddableClass.getClass() ); + this.attributeOverrides = attributeOverrides; String tmpPath = embeddableClass.getEmbeddedAttributeName(); ConfiguredClass parent = embeddableClass.getParent(); while ( parent != null && parent instanceof EmbeddableClass ) { @@ -120,10 +124,20 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource { public Iterable attributeSources() { List attributeList = new ArrayList(); for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes() ) { - attributeList.add( new SingularAttributeSourceImpl( attribute ) ); + AttributeOverride attributeOverride = null; + String tmp = getPath() + "." + attribute.getName(); + if ( attributeOverrides.containsKey( tmp ) ) { + attributeOverride = attributeOverrides.get( tmp ); + } + attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) ); } for ( EmbeddableClass component : embeddableClass.getEmbeddedClasses().values() ) { - attributeList.add( new ComponentAttributeSourceImpl( component ) ); + attributeList.add( + new ComponentAttributeSourceImpl( + component, + embeddableClass.getAttributeOverrideMap() + ) + ); } for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes() ) { attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java index ae796f10b4..f9a9f0939c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java @@ -176,7 +176,7 @@ public class EntitySourceImpl implements EntitySource { attributeList.add( new SingularAttributeSourceImpl( attribute ) ); } for ( EmbeddableClass component : entityClass.getEmbeddedClasses().values() ) { - attributeList.add( new ComponentAttributeSourceImpl( component ) ); + attributeList.add( new ComponentAttributeSourceImpl( component, entityClass.getAttributeOverrideMap() ) ); } for ( AssociationAttribute associationAttribute : entityClass.getAssociationAttributes() ) { attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java index f11a1ab020..247733b4fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java @@ -50,7 +50,7 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity switch ( idType ) { case SIMPLE: { BasicAttribute attribute = getEntityClass().getIdAttributes().iterator().next(); - return new SimpleIdentifierSourceImpl( attribute ); + return new SimpleIdentifierSourceImpl( attribute, getEntityClass().getAttributeOverrideMap() ); } case COMPOSED: { break; @@ -69,8 +69,9 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity @Override public SingularAttributeSource getVersioningAttributeSource() { SingularAttributeSource attributeSource = null; - if ( getEntityClass().getVersionAttribute() != null ) { - attributeSource = new SingularAttributeSourceImpl( getEntityClass().getVersionAttribute() ); + EntityClass entityClass = getEntityClass(); + if ( entityClass.getVersionAttribute() != null ) { + attributeSource = new SingularAttributeSourceImpl( entityClass.getVersionAttribute() ); } return attributeSource; } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java index a0d9f2db64..1dc7899403 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java @@ -23,6 +23,8 @@ */ package org.hibernate.metamodel.source.annotations.entity; +import javax.persistence.AttributeOverride; +import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Embedded; import javax.persistence.Entity; @@ -30,6 +32,7 @@ import javax.persistence.Id; import org.junit.Test; +import org.hibernate.metamodel.binding.BasicAttributeBinding; import org.hibernate.metamodel.binding.ComponentAttributeBinding; import org.hibernate.metamodel.binding.EntityBinding; @@ -43,29 +46,6 @@ import static junit.framework.Assert.assertTrue; * @author Hardy Ferentschik */ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { - @Test - @Resources(annotatedClasses = { User.class, Address.class }) - public void testEmbeddable() { - EntityBinding binding = getEntityBinding( User.class ); - - assertNotNull( binding.locateAttributeBinding( "address" ) ); - assertTrue( binding.locateAttributeBinding( "address" ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - "address" - ); - - // todo - is this really correct? Does the path start w/ the class name - assertEquals( - "Wrong path", - "org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.address", - componentBinding.getPathBase() - ); - - assertNotNull( componentBinding.locateAttributeBinding( "street" ) ); - assertNotNull( componentBinding.locateAttributeBinding( "city" ) ); - assertNotNull( componentBinding.locateAttributeBinding( "postCode" ) ); - } - @Entity class User { @Id @@ -81,6 +61,64 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { String city; String postCode; } + + @Test + @Resources(annotatedClasses = { User.class, Address.class }) + public void testEmbeddable() { + EntityBinding binding = getEntityBinding( User.class ); + + final String componentName = "address"; + assertNotNull( binding.locateAttributeBinding( componentName ) ); + assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); + ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + componentName + ); + + // todo - is this really correct? Does the path start w/ the class name + assertEquals( + "Wrong path", + "org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.address", + componentBinding.getPathBase() + ); + + assertNotNull( componentBinding.locateAttributeBinding( "street" ) ); + assertNotNull( componentBinding.locateAttributeBinding( "city" ) ); + assertNotNull( componentBinding.locateAttributeBinding( "postCode" ) ); + } + + @Entity + @AttributeOverride(name = "embedded.name", column = @Column(name = "FUBAR", length = 42)) + class BaseEntity { + @Id + private int id; + + @Embedded + private EmbeddedEntity embedded; + } + + @Embeddable + class EmbeddedEntity { + String name; + } + + @Test + @Resources(annotatedClasses = { BaseEntity.class, EmbeddedEntity.class }) + public void testEmbeddableWithAttributeOverride() { + EntityBinding binding = getEntityBinding( BaseEntity.class ); + + final String componentName = "embedded"; + assertNotNull( binding.locateAttributeBinding( componentName ) ); + assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); + ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + componentName + ); + + assertNotNull( componentBinding.locateAttributeBinding( "name" ) ); + BasicAttributeBinding nameAttribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "name" ); + org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); + assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getName() ); + assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() ); + } }