From b0f5c9758f76040fb6bdf5603775af300ae89edc Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Fri, 10 Feb 2012 11:25:19 -0600 Subject: [PATCH] HHH-7052 : Bind PluralAttributeKeyBinding --- .../metamodel/internal/source/Binder.java | 147 +++++++++++++++--- ...BasicPluralAttributeElementSourceImpl.java | 21 ++- .../spi/binding/AbstractAttributeBinding.java | 4 + .../AbstractPluralAttributeBinding.java | 11 -- .../AbstractSingularAttributeBinding.java | 4 - .../BasicPluralAttributeElementBinding.java | 34 +++- ...nyToManyPluralAttributeElementBinding.java | 14 +- .../spi/binding/PluralAttributeBinding.java | 9 -- .../binding/PluralAttributeKeyBinding.java | 5 + .../BasicPluralAttributeElementSource.java | 3 +- 10 files changed, 203 insertions(+), 49 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java index 9fa499384c..c6236cbbeb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java @@ -26,8 +26,11 @@ import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.lang.reflect.ParameterizedType; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -58,12 +61,14 @@ import org.hibernate.metamodel.spi.binding.SimpleValueBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.domain.Attribute; import org.hibernate.metamodel.spi.domain.Component; import org.hibernate.metamodel.spi.domain.Entity; import org.hibernate.metamodel.spi.domain.PluralAttribute; import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.ForeignKey; import org.hibernate.metamodel.spi.relational.Identifier; import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.metamodel.spi.relational.SimpleValue; @@ -179,7 +184,8 @@ private EntityBinding doCreateEntityBinding(EntitySource entitySource, EntityBin final EntityBinding entityBinding = createBasicEntityBinding( entitySource, superEntityBinding ); bindSecondaryTables( entitySource, entityBinding ); - bindAttributes( entitySource, entityBinding ); + Deque tableStack = new ArrayDeque( ); + bindAttributes( entitySource, entityBinding, tableStack ); bindTableUniqueConstraints( entitySource, entityBinding ); @@ -359,7 +365,9 @@ private void bindIdentifier(RootEntitySource entitySource, EntityBinding entityB } } - private void bindSimpleIdentifier(SimpleIdentifierSource identifierSource, EntityBinding entityBinding) { + private void bindSimpleIdentifier( + SimpleIdentifierSource identifierSource, + EntityBinding entityBinding) { final BasicAttributeBinding idAttributeBinding = doBasicSingularAttributeBindingCreation( identifierSource.getIdentifierAttributeSource(), entityBinding ); @@ -439,7 +447,10 @@ private void bindDiscriminatorValue(SubclassEntitySource entitySource, EntityBin entityBinding.setDiscriminatorMatchValue( discriminatorValue ); } - private void bindAttributes(AttributeSourceContainer attributeSourceContainer, AttributeBindingContainer attributeBindingContainer) { + private void bindAttributes( + AttributeSourceContainer attributeSourceContainer, + AttributeBindingContainer attributeBindingContainer, + Deque tableStack) { // todo : we really need the notion of a Stack here for the table from which the columns come for binding these attributes. // todo : adding the concept (interface) of a source of attribute metadata would allow reuse of this method for entity, component, unique-key, etc // for now, simply assume all columns come from the base table.... @@ -448,19 +459,22 @@ private void bindAttributes(AttributeSourceContainer attributeSourceContainer, A if ( attributeSource.isSingular() ) { final SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource; if ( singularAttributeSource.getNature() == SingularAttributeNature.COMPONENT ) { - bindComponent( (ComponentAttributeSource) singularAttributeSource, attributeBindingContainer ); + bindComponent( (ComponentAttributeSource) singularAttributeSource, attributeBindingContainer, tableStack ); } else { doBasicSingularAttributeBindingCreation( singularAttributeSource, attributeBindingContainer ); } } else { - bindPersistentCollection( (PluralAttributeSource) attributeSource, attributeBindingContainer ); + bindPersistentCollection( (PluralAttributeSource) attributeSource, attributeBindingContainer, tableStack ); } } } - private void bindComponent(ComponentAttributeSource attributeSource, AttributeBindingContainer container) { + private void bindComponent( + ComponentAttributeSource attributeSource, + AttributeBindingContainer container, + Deque tableStack) { final String attributeName = attributeSource.getName(); SingularAttribute attribute = container.getAttributeContainer().locateComponentAttribute( attributeName ); if ( attribute == null ) { @@ -485,10 +499,13 @@ private void bindComponent(ComponentAttributeSource attributeSource, AttributeBi buildMetaAttributeContext( attributeSource.metaAttributes(), container.getMetaAttributeContext() ) ); - bindAttributes( attributeSource, componentAttributeBinding ); + bindAttributes( attributeSource, componentAttributeBinding, tableStack ); } - private void bindPersistentCollection(PluralAttributeSource attributeSource, AttributeBindingContainer attributeBindingContainer) { + private void bindPersistentCollection( + PluralAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + Deque tableStack) { final PluralAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() .locatePluralAttribute( attributeSource.getName() ); final AbstractPluralAttributeBinding pluralAttributeBinding; @@ -521,7 +538,7 @@ else if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.SE bindCollectionTable( attributeSource, pluralAttributeBinding ); bindSortingAndOrdering( attributeSource, pluralAttributeBinding ); - bindCollectionKey( attributeSource, pluralAttributeBinding ); + bindCollectionKey( attributeSource, pluralAttributeBinding, tableStack ); bindCollectionElement( attributeSource, pluralAttributeBinding ); bindCollectionIndex( attributeSource, pluralAttributeBinding ); @@ -654,18 +671,84 @@ private void bindCollectionTable( } private void bindCollectionKey( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { + PluralAttributeSource attributeSource, + AbstractPluralAttributeBinding pluralAttributeBinding, + Deque tableStack) { + + TableSpecification targetTable = tableStack.peekLast(); pluralAttributeBinding.getPluralAttributeKeyBinding().prepareForeignKey( attributeSource.getKeySource().getExplicitForeignKeyName(), + //tableStack.peekLast().getLogicalName() null // todo : handle secondary table names ); pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey().setDeleteRule( attributeSource.getKeySource().getOnDeleteAction() ); - // todo : need to bind "relational values", account for property-ref - } + final ForeignKey foreignKey = pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey(); + Iterator targetValueBindings = null; + if ( attributeSource.getKeySource().getReferencedEntityAttributeName() != null ) { + final EntityBinding ownerEntityBinding = pluralAttributeBinding.getContainer().seekEntityBinding(); + final AttributeBinding referencedAttributeBinding = + ownerEntityBinding + .locateAttributeBinding( attributeSource.getKeySource().getReferencedEntityAttributeName() ); + if ( ! referencedAttributeBinding.getAttribute().isSingular() ) { + throw new MappingException( + String.format( + "Collection (%s) property-ref is a plural attribute (%s); must be singular.", + pluralAttributeBinding.getAttribute().getRole(), + referencedAttributeBinding + ), + currentBindingContext.getOrigin() + ); + } + targetValueBindings = ( ( SingularAttributeBinding) referencedAttributeBinding ).getSimpleValueBindings().iterator(); + } + for ( RelationalValueSource valueSource : attributeSource.getKeySource().getValueSources() ) { + SimpleValue targetValue = null; + if ( targetValueBindings != null ) { + if ( ! targetValueBindings.hasNext() ) { + throw new MappingException( + String.format( + "More collection key source columns than target columns for collection: %s", + pluralAttributeBinding.getAttribute().getRole() + ), + currentBindingContext.getOrigin() + ); + } + targetValue = targetValueBindings.next().getSimpleValue(); + } + if ( ColumnSource.class.isInstance( valueSource ) ) { + final ColumnSource columnSource = ColumnSource.class.cast( valueSource ); + final Column column = makeColumn( columnSource, pluralAttributeBinding.getCollectionTable() ); + if ( targetValue != null && ! Column.class.isInstance( targetValue ) ) { + throw new MappingException( + String.format( + "Type mismatch between collection key source and target; collection: %s; source column (%s) corresponds with target derived value (%s).", + pluralAttributeBinding.getAttribute().getRole(), + columnSource.getName(), + DerivedValue.class.cast( targetValue ).getExpression() + ), + currentBindingContext.getOrigin() + ); + } + foreignKey.addColumnMapping( column, Column.class.cast( targetValue ) ); + } + else { + // TODO: deal with formulas??? + } + } + if ( targetValueBindings != null && targetValueBindings.hasNext() ) { + throw new MappingException( + String.format( + "More collection key target columns than source columns for collection: %s", + pluralAttributeBinding.getAttribute().getRole() + ), + currentBindingContext.getOrigin() + ); + } + } + private void bindCollectionElement( PluralAttributeSource attributeSource, AbstractPluralAttributeBinding pluralAttributeBinding) { @@ -678,7 +761,10 @@ private void bindCollectionElement( pluralAttributeBinding.getAttribute(), basicCollectionElement ); - // todo : temp + bindBasicPluralElementRelationalValues( + basicElementSource, + basicCollectionElement + ); return; } // todo : implement @@ -690,6 +776,18 @@ private void bindCollectionElement( ); } + private void bindBasicPluralElementRelationalValues( + RelationalValueSourceContainer relationalValueSourceContainer, + BasicPluralAttributeElementBinding elementBinding) { + elementBinding.setSimpleValueBindings( + createSimpleRelationalValues( + relationalValueSourceContainer, + elementBinding.getPluralAttributeBinding().getContainer(), + elementBinding.getPluralAttributeBinding().getAttribute() + ) + ); + } + private void bindCollectionIndex( PluralAttributeSource attributeSource, AbstractPluralAttributeBinding pluralAttributeBinding) { @@ -986,12 +1084,25 @@ private void bindTableUniqueConstraints(EntitySource entitySource, EntityBinding private void bindRelationalValues( RelationalValueSourceContainer relationalValueSourceContainer, SingularAttributeBinding attributeBinding) { + attributeBinding.setSimpleValueBindings( + createSimpleRelationalValues( + relationalValueSourceContainer, + attributeBinding.getContainer(), + attributeBinding.getAttribute() + ) + ); + } + + private List createSimpleRelationalValues( + RelationalValueSourceContainer relationalValueSourceContainer, + AttributeBindingContainer attributeBindingContainer, + Attribute attribute) { List valueBindings = new ArrayList(); if ( !relationalValueSourceContainer.relationalValueSources().isEmpty() ) { for ( RelationalValueSource valueSource : relationalValueSourceContainer.relationalValueSources() ) { - final TableSpecification table = attributeBinding.getContainer() + final TableSpecification table = attributeBindingContainer .seekEntityBinding() .locateTable( valueSource.getContainingTableName() ); @@ -1018,9 +1129,9 @@ private void bindRelationalValues( else { String name = metadata.getOptions() .getNamingStrategy() - .propertyToColumnName( attributeBinding.getAttribute().getName() ); + .propertyToColumnName( attribute.getName() ); name = quoteIdentifier( name ); - Column column = attributeBinding.getContainer() + Column column = attributeBindingContainer .seekEntityBinding() .getPrimaryTable() .locateOrCreateColumn( name ); @@ -1033,7 +1144,7 @@ private void bindRelationalValues( ) ); } - attributeBinding.setSimpleValueBindings( valueBindings ); + return valueBindings; } private String quoteIdentifier(String identifier) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java index 253216f287..b16f8df661 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java @@ -52,12 +52,12 @@ public String getContainingTableName() { @Override public boolean isIncludedInInsertByDefault() { - return true; + return BasicPluralAttributeElementSourceImpl.this.areValuesIncludedInInsertByDefault(); } @Override public boolean isIncludedInUpdateByDefault() { - return true; + return BasicPluralAttributeElementSourceImpl.this.areValuesIncludedInUpdateByDefault(); } @Override @@ -107,10 +107,25 @@ public PluralAttributeElementNature getNature() { } @Override - public List getValueSources() { + public List relationalValueSources() { return valueSources; } + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + @Override public ExplicitHibernateTypeSource getExplicitHibernateTypeSource() { return typeSource; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java index 2ac452dc46..72f4f16f8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java @@ -65,6 +65,10 @@ public Attribute getAttribute() { return attribute; } + protected String getRole() { + return getContainer().getPathBase() + '.' + getAttribute().getName(); + } + @Override public HibernateTypeDescriptor getHibernateTypeDescriptor() { return hibernateTypeDescriptor; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java index ba4ab0a5cb..cad3324296 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java @@ -48,7 +48,6 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi private Caching caching; - private boolean inverse; private boolean mutable = true; private Class collectionPersisterClass; @@ -108,7 +107,6 @@ private AbstractPluralAttributeElementBinding interpretNature(PluralAttributeEle // extraLazy = state.isExtraLazy(); // pluralAttributeElementBinding.setNodeName( state.getElementNodeName() ); // pluralAttributeElementBinding.setTypeName( state.getElementTypeName() ); -// inverse = state.isInverse(); // mutable = state.isMutable(); // subselectLoadable = state.isSubselectLoadable(); // if ( isSubselectLoadable() ) { @@ -244,15 +242,6 @@ public void setWhere(String where) { this.where = where; } - @Override - public boolean isInverse() { - return inverse; - } - - public void setInverse(boolean inverse) { - this.inverse = inverse; - } - @Override public boolean isMutable() { return mutable; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java index 7794d01e0a..69a8b7d540 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java @@ -78,10 +78,6 @@ public void setSimpleValueBindings(Iterable simpleValueBindi } } - private String getRole() { - return getContainer().getPathBase() + '.' + getAttribute().getName(); - } - @Override public int getSimpleValueSpan() { checkValueBinding(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java index ad97fb66de..4bec64e06a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java @@ -23,6 +23,13 @@ */ package org.hibernate.metamodel.spi.binding; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.spi.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.Tuple; +import org.hibernate.metamodel.spi.relational.Value; + /** * Describes plural attributes of {@link PluralAttributeElementNature#BASIC} elements * @@ -30,13 +37,38 @@ * @author Gail Badner */ public class BasicPluralAttributeElementBinding extends AbstractPluralAttributeElementBinding { + private Value value; + private List simpleValueBindings = new ArrayList(); + + private boolean hasDerivedValue; + private boolean isNullable = true; public BasicPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { super( binding ); } - + @Override public PluralAttributeElementNature getPluralAttributeElementNature() { return PluralAttributeElementNature.BASIC; } + + public void setSimpleValueBindings(Iterable simpleValueBindings) { + List values = new ArrayList(); + for ( SimpleValueBinding simpleValueBinding : simpleValueBindings ) { + this.simpleValueBindings.add( simpleValueBinding ); + values.add( simpleValueBinding.getSimpleValue() ); + this.hasDerivedValue = this.hasDerivedValue || simpleValueBinding.isDerived(); + this.isNullable = this.isNullable && simpleValueBinding.isNullable(); + } + if ( values.size() == 1 ) { + this.value = values.get( 0 ); + } + else { + final Tuple tuple = values.get( 0 ).getTable().createTuple( getPluralAttributeBinding().getRole() ); + for ( SimpleValue value : values ) { + tuple.addValue( value ); + } + this.value = tuple; + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java index f2dd023c2f..464af28118 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java @@ -25,6 +25,9 @@ import java.util.HashMap; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.Value; + /** * Describes plural attributes of {@link PluralAttributeElementNature#MANY_TO_MANY} elements * @@ -35,7 +38,8 @@ public class ManyToManyPluralAttributeElementBinding extends AbstractPluralAttri private final java.util.Map manyToManyFilters = new HashMap(); private String manyToManyWhere; private String manyToManyOrderBy; - + // TODO: really should have value defined (which defines table), but may not know + private Value value; ManyToManyPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { super( binding ); @@ -61,4 +65,12 @@ public String getManyToManyOrderBy() { public void setManyToManyOrderBy(String manyToManyOrderBy) { this.manyToManyOrderBy = manyToManyOrderBy; } + + public Value getValue() { + return value; + } + + public void setValue(Value value) { + this.value = value; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java index dee59dc424..437bd2f9f6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java @@ -57,13 +57,6 @@ public interface PluralAttributeBinding extends AttributeBinding { */ public PluralAttributeElementBinding getPluralAttributeElementBinding(); - - - - - - - public TableSpecification getCollectionTable(); public boolean isMutable(); @@ -92,7 +85,5 @@ public interface PluralAttributeBinding extends AttributeBinding { java.util.Map getFilterMap(); - boolean isInverse(); - String getOrderBy(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java index f70daa8962..b15c0fa67b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java @@ -25,6 +25,7 @@ import org.hibernate.AssertionFailure; import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.TableSpecification; /** @@ -81,6 +82,10 @@ public boolean isInverse() { return inverse; } + public void setInverse(boolean inverse) { + this.inverse = inverse; + } + public HibernateTypeDescriptor getHibernateTypeDescriptor() { return hibernateTypeDescriptor; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java index 6a8b56cc1c..19a869a666 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java @@ -28,7 +28,6 @@ /** * @author Steve Ebersole */ -public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource { - public List getValueSources(); +public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource, RelationalValueSourceContainer { public ExplicitHibernateTypeSource getExplicitHibernateTypeSource(); }