HHH-7052 : Bind PluralAttributeKeyBinding

This commit is contained in:
Gail Badner 2012-02-10 11:25:19 -06:00
parent eae715584b
commit b0f5c9758f
10 changed files with 203 additions and 49 deletions

View File

@ -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<TableSpecification> tableStack = new ArrayDeque<TableSpecification>( );
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<TableSpecification> 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<TableSpecification> 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<TableSpecification> 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<TableSpecification> 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<SimpleValueBinding> 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<SimpleValueBinding> createSimpleRelationalValues(
RelationalValueSourceContainer relationalValueSourceContainer,
AttributeBindingContainer attributeBindingContainer,
Attribute attribute) {
List<SimpleValueBinding> valueBindings = new ArrayList<SimpleValueBinding>();
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) {

View File

@ -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<RelationalValueSource> getValueSources() {
public List<RelationalValueSource> 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;

View File

@ -65,6 +65,10 @@ public Attribute getAttribute() {
return attribute;
}
protected String getRole() {
return getContainer().getPathBase() + '.' + getAttribute().getName();
}
@Override
public HibernateTypeDescriptor getHibernateTypeDescriptor() {
return hibernateTypeDescriptor;

View File

@ -48,7 +48,6 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi
private Caching caching;
private boolean inverse;
private boolean mutable = true;
private Class<? extends CollectionPersister> 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;

View File

@ -78,10 +78,6 @@ public void setSimpleValueBindings(Iterable<SimpleValueBinding> simpleValueBindi
}
}
private String getRole() {
return getContainer().getPathBase() + '.' + getAttribute().getName();
}
@Override
public int getSimpleValueSpan() {
checkValueBinding();

View File

@ -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<SimpleValueBinding> simpleValueBindings = new ArrayList<SimpleValueBinding>();
private boolean hasDerivedValue;
private boolean isNullable = true;
public BasicPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) {
super( binding );
}
@Override
public PluralAttributeElementNature getPluralAttributeElementNature() {
return PluralAttributeElementNature.BASIC;
}
public void setSimpleValueBindings(Iterable<SimpleValueBinding> simpleValueBindings) {
List<SimpleValue> values = new ArrayList<SimpleValue>();
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;
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -28,7 +28,6 @@
/**
* @author Steve Ebersole
*/
public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource {
public List<RelationalValueSource> getValueSources();
public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource, RelationalValueSourceContainer {
public ExplicitHibernateTypeSource getExplicitHibernateTypeSource();
}