HHH-6393 Adding more tests and implementing nested embeddables
This commit is contained in:
parent
e875bb6004
commit
b1478946db
|
@ -25,11 +25,13 @@ package org.hibernate.metamodel.source.annotations.entity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jboss.jandex.AnnotationInstance;
|
import org.jboss.jandex.AnnotationInstance;
|
||||||
|
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.Value;
|
import org.hibernate.internal.util.Value;
|
||||||
import org.hibernate.mapping.PropertyGeneration;
|
import org.hibernate.mapping.PropertyGeneration;
|
||||||
import org.hibernate.metamodel.source.LocalBindingContext;
|
import org.hibernate.metamodel.source.LocalBindingContext;
|
||||||
|
@ -53,21 +55,22 @@ import org.hibernate.metamodel.source.binder.SingularAttributeNature;
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
|
public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
|
||||||
|
private static final String PATH_SEPERATOR = ".";
|
||||||
private final EmbeddableClass embeddableClass;
|
private final EmbeddableClass embeddableClass;
|
||||||
private final Value<Class<?>> classReference;
|
private final Value<Class<?>> classReference;
|
||||||
private final Map<String, AttributeOverride> attributeOverrides;
|
private final Map<String, AttributeOverride> attributeOverrides;
|
||||||
private final String path;
|
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.embeddableClass = embeddableClass;
|
||||||
this.classReference = new Value<Class<?>>( embeddableClass.getClass() );
|
this.classReference = new Value<Class<?>>( embeddableClass.getClass() );
|
||||||
this.attributeOverrides = attributeOverrides;
|
this.attributeOverrides = attributeOverrides;
|
||||||
String tmpPath = embeddableClass.getEmbeddedAttributeName();
|
if ( StringHelper.isEmpty( parentPath ) ) {
|
||||||
ConfiguredClass parent = embeddableClass.getParent();
|
path = embeddableClass.getEmbeddedAttributeName();
|
||||||
while ( parent != null && parent instanceof EmbeddableClass ) {
|
}
|
||||||
tmpPath = ( (EmbeddableClass) parent ).getEmbeddedAttributeName() + "." + tmpPath;
|
else {
|
||||||
|
path = parentPath + "." + embeddableClass.getEmbeddedAttributeName();
|
||||||
}
|
}
|
||||||
path = tmpPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -125,17 +128,18 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
|
||||||
List<AttributeSource> attributeList = new ArrayList<AttributeSource>();
|
List<AttributeSource> attributeList = new ArrayList<AttributeSource>();
|
||||||
for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes() ) {
|
for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes() ) {
|
||||||
AttributeOverride attributeOverride = null;
|
AttributeOverride attributeOverride = null;
|
||||||
String tmp = getPath() + "." + attribute.getName();
|
String tmp = getPath() + PATH_SEPERATOR + attribute.getName();
|
||||||
if ( attributeOverrides.containsKey( tmp ) ) {
|
if ( attributeOverrides.containsKey( tmp ) ) {
|
||||||
attributeOverride = attributeOverrides.get( tmp );
|
attributeOverride = attributeOverrides.get( tmp );
|
||||||
}
|
}
|
||||||
attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) );
|
attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) );
|
||||||
}
|
}
|
||||||
for ( EmbeddableClass component : embeddableClass.getEmbeddedClasses().values() ) {
|
for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) {
|
||||||
attributeList.add(
|
attributeList.add(
|
||||||
new ComponentAttributeSourceImpl(
|
new ComponentAttributeSourceImpl(
|
||||||
component,
|
embeddable,
|
||||||
embeddableClass.getAttributeOverrideMap()
|
getPath(),
|
||||||
|
createAggregatedOverrideMap()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -191,13 +195,11 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLazy() {
|
public boolean isLazy() {
|
||||||
// todo : implement
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isIncludedInOptimisticLocking() {
|
public boolean isIncludedInOptimisticLocking() {
|
||||||
// todo : implement
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,4 +217,29 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
|
||||||
public boolean areValuesNullableByDefault() {
|
public boolean areValuesNullableByDefault() {
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,7 +608,7 @@ public class ConfiguredClass {
|
||||||
JPADotNames.ATTRIBUTE_OVERRIDE
|
JPADotNames.ATTRIBUTE_OVERRIDE
|
||||||
);
|
);
|
||||||
if ( attributeOverrideAnnotation != null ) {
|
if ( attributeOverrideAnnotation != null ) {
|
||||||
String prefix = createPathPrefix( attributeOverrideAnnotation );
|
String prefix = createPathPrefix( attributeOverrideAnnotation.target() );
|
||||||
AttributeOverride override = new AttributeOverride( prefix, attributeOverrideAnnotation );
|
AttributeOverride override = new AttributeOverride( prefix, attributeOverrideAnnotation );
|
||||||
attributeOverrideList.put( override.getAttributePath(), override );
|
attributeOverrideList.put( override.getAttributePath(), override );
|
||||||
}
|
}
|
||||||
|
@ -620,7 +620,7 @@ public class ConfiguredClass {
|
||||||
if ( attributeOverridesAnnotation != null ) {
|
if ( attributeOverridesAnnotation != null ) {
|
||||||
AnnotationInstance[] annotationInstances = attributeOverridesAnnotation.value().asNestedArray();
|
AnnotationInstance[] annotationInstances = attributeOverridesAnnotation.value().asNestedArray();
|
||||||
for ( AnnotationInstance annotationInstance : annotationInstances ) {
|
for ( AnnotationInstance annotationInstance : annotationInstances ) {
|
||||||
String prefix = createPathPrefix( annotationInstance );
|
String prefix = createPathPrefix( attributeOverridesAnnotation.target() );
|
||||||
AttributeOverride override = new AttributeOverride( prefix, annotationInstance );
|
AttributeOverride override = new AttributeOverride( prefix, annotationInstance );
|
||||||
attributeOverrideList.put( override.getAttributePath(), override );
|
attributeOverrideList.put( override.getAttributePath(), override );
|
||||||
}
|
}
|
||||||
|
@ -628,9 +628,8 @@ public class ConfiguredClass {
|
||||||
return attributeOverrideList;
|
return attributeOverrideList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createPathPrefix(AnnotationInstance attributeOverrideAnnotation) {
|
private String createPathPrefix(AnnotationTarget target) {
|
||||||
String prefix = null;
|
String prefix = null;
|
||||||
AnnotationTarget target = attributeOverrideAnnotation.target();
|
|
||||||
if ( target instanceof FieldInfo || target instanceof MethodInfo ) {
|
if ( target instanceof FieldInfo || target instanceof MethodInfo ) {
|
||||||
prefix = JandexHelper.getPropertyName( target );
|
prefix = JandexHelper.getPropertyName( target );
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ public class EntitySourceImpl implements EntitySource {
|
||||||
attributeList.add( new SingularAttributeSourceImpl( attribute ) );
|
attributeList.add( new SingularAttributeSourceImpl( attribute ) );
|
||||||
}
|
}
|
||||||
for ( EmbeddableClass component : entityClass.getEmbeddedClasses().values() ) {
|
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() ) {
|
for ( AssociationAttribute associationAttribute : entityClass.getAssociationAttributes() ) {
|
||||||
attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) );
|
attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) );
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.metamodel.source.annotations.entity;
|
package org.hibernate.metamodel.source.annotations.entity;
|
||||||
|
|
||||||
import javax.persistence.AttributeOverride;
|
import javax.persistence.AttributeOverride;
|
||||||
|
import javax.persistence.AttributeOverrides;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Embedded;
|
import javax.persistence.Embedded;
|
||||||
|
@ -52,22 +53,22 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private Address address;
|
private Phone phone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Embeddable
|
@Embeddable
|
||||||
class Address {
|
class Phone {
|
||||||
String street;
|
String countryCode;
|
||||||
String city;
|
String areaCode;
|
||||||
String postCode;
|
String number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Resources(annotatedClasses = { User.class, Address.class })
|
@Resources(annotatedClasses = { User.class, Phone.class })
|
||||||
public void testEmbeddable() {
|
public void testEmbeddable() {
|
||||||
EntityBinding binding = getEntityBinding( User.class );
|
EntityBinding binding = getEntityBinding( User.class );
|
||||||
|
|
||||||
final String componentName = "address";
|
final String componentName = "phone";
|
||||||
assertNotNull( binding.locateAttributeBinding( componentName ) );
|
assertNotNull( binding.locateAttributeBinding( componentName ) );
|
||||||
assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding );
|
assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding );
|
||||||
ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding(
|
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
|
// todo - is this really correct? Does the path start w/ the class name
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"Wrong path",
|
"Wrong path",
|
||||||
"org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.address",
|
"org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.phone",
|
||||||
componentBinding.getPathBase()
|
componentBinding.getPathBase()
|
||||||
);
|
);
|
||||||
|
|
||||||
assertNotNull( componentBinding.locateAttributeBinding( "street" ) );
|
assertNotNull( componentBinding.locateAttributeBinding( "countryCode" ) );
|
||||||
assertNotNull( componentBinding.locateAttributeBinding( "city" ) );
|
assertNotNull( componentBinding.locateAttributeBinding( "areaCode" ) );
|
||||||
assertNotNull( componentBinding.locateAttributeBinding( "postCode" ) );
|
assertNotNull( componentBinding.locateAttributeBinding( "number" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@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 column name", "FUBAR", column.getColumnName().getName() );
|
||||||
assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() );
|
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()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue