HHH-6393 Adding more tests and implementing nested embeddables

This commit is contained in:
Hardy Ferentschik 2011-08-02 12:00:05 +02:00
parent e875bb6004
commit b1478946db
4 changed files with 190 additions and 28 deletions

View File

@ -25,11 +25,13 @@ package org.hibernate.metamodel.source.annotations.entity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jboss.jandex.AnnotationInstance;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.Value;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.source.LocalBindingContext;
@ -53,21 +55,22 @@ import org.hibernate.metamodel.source.binder.SingularAttributeNature;
* @author Hardy Ferentschik
*/
public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
private static final String PATH_SEPERATOR = ".";
private final EmbeddableClass embeddableClass;
private final Value<Class<?>> classReference;
private final Map<String, AttributeOverride> attributeOverrides;
private final String path;
public ComponentAttributeSourceImpl(EmbeddableClass embeddableClass, Map<String, AttributeOverride> attributeOverrides) {
public ComponentAttributeSourceImpl(EmbeddableClass embeddableClass, String parentPath, Map<String, AttributeOverride> attributeOverrides) {
this.embeddableClass = embeddableClass;
this.classReference = new Value<Class<?>>( embeddableClass.getClass() );
this.attributeOverrides = attributeOverrides;
String tmpPath = embeddableClass.getEmbeddedAttributeName();
ConfiguredClass parent = embeddableClass.getParent();
while ( parent != null && parent instanceof EmbeddableClass ) {
tmpPath = ( (EmbeddableClass) parent ).getEmbeddedAttributeName() + "." + tmpPath;
if ( StringHelper.isEmpty( parentPath ) ) {
path = embeddableClass.getEmbeddedAttributeName();
}
else {
path = parentPath + "." + embeddableClass.getEmbeddedAttributeName();
}
path = tmpPath;
}
@Override
@ -125,17 +128,18 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
List<AttributeSource> attributeList = new ArrayList<AttributeSource>();
for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes() ) {
AttributeOverride attributeOverride = null;
String tmp = getPath() + "." + attribute.getName();
String tmp = getPath() + PATH_SEPERATOR + attribute.getName();
if ( attributeOverrides.containsKey( tmp ) ) {
attributeOverride = attributeOverrides.get( tmp );
}
attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) );
}
for ( EmbeddableClass component : embeddableClass.getEmbeddedClasses().values() ) {
for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) {
attributeList.add(
new ComponentAttributeSourceImpl(
component,
embeddableClass.getAttributeOverrideMap()
embeddable,
getPath(),
createAggregatedOverrideMap()
)
);
}
@ -191,13 +195,11 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
@Override
public boolean isLazy() {
// todo : implement
return false;
}
@Override
public boolean isIncludedInOptimisticLocking() {
// todo : implement
return true;
}
@ -215,4 +217,29 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
public boolean areValuesNullableByDefault() {
return true;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "ComponentAttributeSourceImpl" );
sb.append( "{embeddableClass=" ).append( embeddableClass.getConfiguredClass().getSimpleName() );
sb.append( '}' );
return sb.toString();
}
private Map<String, AttributeOverride> createAggregatedOverrideMap() {
// add all overrides passed down to this instance - they override overrides ;-) which are defined further down
// the embeddable chain
Map<String, AttributeOverride> aggregatedOverrideMap = new HashMap<String, AttributeOverride>(
attributeOverrides
);
for ( Map.Entry<String, AttributeOverride> entry : embeddableClass.getAttributeOverrideMap().entrySet() ) {
String fullPath = getPath() + PATH_SEPERATOR + entry.getKey();
if ( !aggregatedOverrideMap.containsKey( fullPath ) ) {
aggregatedOverrideMap.put( fullPath, entry.getValue() );
}
}
return aggregatedOverrideMap;
}
}

View File

@ -608,7 +608,7 @@ public class ConfiguredClass {
JPADotNames.ATTRIBUTE_OVERRIDE
);
if ( attributeOverrideAnnotation != null ) {
String prefix = createPathPrefix( attributeOverrideAnnotation );
String prefix = createPathPrefix( attributeOverrideAnnotation.target() );
AttributeOverride override = new AttributeOverride( prefix, attributeOverrideAnnotation );
attributeOverrideList.put( override.getAttributePath(), override );
}
@ -620,7 +620,7 @@ public class ConfiguredClass {
if ( attributeOverridesAnnotation != null ) {
AnnotationInstance[] annotationInstances = attributeOverridesAnnotation.value().asNestedArray();
for ( AnnotationInstance annotationInstance : annotationInstances ) {
String prefix = createPathPrefix( annotationInstance );
String prefix = createPathPrefix( attributeOverridesAnnotation.target() );
AttributeOverride override = new AttributeOverride( prefix, annotationInstance );
attributeOverrideList.put( override.getAttributePath(), override );
}
@ -628,9 +628,8 @@ public class ConfiguredClass {
return attributeOverrideList;
}
private String createPathPrefix(AnnotationInstance attributeOverrideAnnotation) {
private String createPathPrefix(AnnotationTarget target) {
String prefix = null;
AnnotationTarget target = attributeOverrideAnnotation.target();
if ( target instanceof FieldInfo || target instanceof MethodInfo ) {
prefix = JandexHelper.getPropertyName( target );
}

View File

@ -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, entityClass.getAttributeOverrideMap() ) );
attributeList.add( new ComponentAttributeSourceImpl( component, "", entityClass.getAttributeOverrideMap() ) );
}
for ( AssociationAttribute associationAttribute : entityClass.getAssociationAttributes() ) {
attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) );

View File

@ -24,6 +24,7 @@
package org.hibernate.metamodel.source.annotations.entity;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
@ -52,22 +53,22 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase {
private int id;
@Embedded
private Address address;
private Phone phone;
}
@Embeddable
class Address {
String street;
String city;
String postCode;
class Phone {
String countryCode;
String areaCode;
String number;
}
@Test
@Resources(annotatedClasses = { User.class, Address.class })
@Resources(annotatedClasses = { User.class, Phone.class })
public void testEmbeddable() {
EntityBinding binding = getEntityBinding( User.class );
final String componentName = "address";
final String componentName = "phone";
assertNotNull( binding.locateAttributeBinding( componentName ) );
assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding );
ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding(
@ -77,13 +78,13 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase {
// 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",
"org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.phone",
componentBinding.getPathBase()
);
assertNotNull( componentBinding.locateAttributeBinding( "street" ) );
assertNotNull( componentBinding.locateAttributeBinding( "city" ) );
assertNotNull( componentBinding.locateAttributeBinding( "postCode" ) );
assertNotNull( componentBinding.locateAttributeBinding( "countryCode" ) );
assertNotNull( componentBinding.locateAttributeBinding( "areaCode" ) );
assertNotNull( componentBinding.locateAttributeBinding( "number" ) );
}
@Entity
@ -119,6 +120,141 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase {
assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getName() );
assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() );
}
@Embeddable
public class Address {
protected String street;
protected String city;
protected String state;
@Embedded
protected Zipcode zipcode;
}
@Embeddable
public class Zipcode {
protected String zip;
protected String plusFour;
}
@Entity
public class Customer {
@Id
protected Integer id;
protected String name;
@AttributeOverrides( {
@AttributeOverride(name = "state",
column = @Column(name = "ADDR_STATE")),
@AttributeOverride(name = "zipcode.zip",
column = @Column(name = "ADDR_ZIP"))
})
@Embedded
protected Address address;
}
@Test
@Resources(annotatedClasses = { Zipcode.class, Address.class, Customer.class })
public void testNestedEmbeddable() {
EntityBinding binding = getEntityBinding( Customer.class );
final String addressComponentName = "address";
assertNotNull( binding.locateAttributeBinding( addressComponentName ) );
assertTrue( binding.locateAttributeBinding( addressComponentName ) instanceof ComponentAttributeBinding );
ComponentAttributeBinding attributeComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding(
addressComponentName
);
assertNotNull( attributeComponentBinding.locateAttributeBinding( "street" ) );
assertNotNull( attributeComponentBinding.locateAttributeBinding( "city" ) );
assertNotNull( attributeComponentBinding.locateAttributeBinding( "state" ) );
BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeComponentBinding.locateAttributeBinding(
"state"
);
org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) stateAttribute.getValue();
assertEquals(
"Attribute override specifies a custom column name",
"ADDR_STATE",
column.getColumnName().getName()
);
final String zipComponentName = "zipcode";
assertNotNull( attributeComponentBinding.locateAttributeBinding( zipComponentName ) );
assertTrue( attributeComponentBinding.locateAttributeBinding( zipComponentName ) instanceof ComponentAttributeBinding );
ComponentAttributeBinding zipComponentBinding = (ComponentAttributeBinding) attributeComponentBinding.locateAttributeBinding(
zipComponentName
);
BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipComponentBinding.locateAttributeBinding( "zip" );
column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue();
assertEquals(
"Attribute override specifies a custom column name",
"ADDR_ZIP",
column.getColumnName().getName()
);
}
@Embeddable
public class A {
@Embedded
@AttributeOverrides( {
@AttributeOverride(name = "foo", column = @Column(name = "BAR")),
@AttributeOverride(name = "fubar", column = @Column(name = "A_WINS"))
})
protected B b;
}
@Embeddable
public class B {
protected String foo;
private String fubar;
}
@Entity
public class C {
@Id
int id;
@Embedded
@AttributeOverride(name = "b.fubar", column = @Column(name = "C_WINS"))
protected A a;
}
@Test
@Resources(annotatedClasses = { A.class, B.class, C.class })
public void testAttributeOverrideInEmbeddable() {
EntityBinding binding = getEntityBinding( C.class );
final String aComponentName = "a";
assertNotNull( binding.locateAttributeBinding( aComponentName ) );
assertTrue( binding.locateAttributeBinding( aComponentName ) instanceof ComponentAttributeBinding );
ComponentAttributeBinding aComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding(
aComponentName
);
final String bComponentName = "b";
assertNotNull( aComponentBinding.locateAttributeBinding( bComponentName ) );
assertTrue( aComponentBinding.locateAttributeBinding( bComponentName ) instanceof ComponentAttributeBinding );
ComponentAttributeBinding bComponentBinding = (ComponentAttributeBinding) aComponentBinding.locateAttributeBinding(
bComponentName
);
BasicAttributeBinding attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "foo" );
org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) attribute.getValue();
assertEquals(
"Attribute override specifies a custom column name",
"BAR",
column.getColumnName().getName()
);
attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "fubar" );
column = (org.hibernate.metamodel.relational.Column) attribute.getValue();
assertEquals(
"Attribute override specifies a custom column name",
"C_WINS",
column.getColumnName().getName()
);
}
}