HHH-8722 HHH-8723 : Reorg AbstractLoadPlanBuildingAssociationVisitationStrategy and add Any support

This commit is contained in:
Gail Badner 2013-11-18 21:44:06 -08:00
parent 4e6f3a9753
commit de7cddc879
5 changed files with 121 additions and 32 deletions

View File

@ -390,6 +390,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
final Type attributeType = attributeDefinition.getType();
final boolean isAnyType = attributeType.isAnyType();
final boolean isComponentType = attributeType.isComponentType();
final boolean isAssociationType = attributeType.isAssociationType();
final boolean isBasicType = ! ( isComponentType || isAssociationType );
@ -397,6 +398,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
if ( isBasicType ) {
return true;
}
else if ( isAnyType ) {
// If isAnyType is true, then isComponentType and isAssociationType will also be true
// so need to check isAnyType first so that it is handled properly.
return handleAnyAttribute( (AssociationAttributeDefinition) attributeDefinition );
}
else if ( isAssociationType ) {
return handleAssociationAttribute( (AssociationAttributeDefinition) attributeDefinition );
}
@ -553,7 +559,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
}
@Override
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
public void foundAny(AnyMappingDefinition anyDefinition) {
// do nothing.
}
protected boolean handleAnyAttribute(AssociationAttributeDefinition attributeDefinition) {
// for ANY mappings we need to build a Fetch:
// 1) fetch type is SELECT, timing might be IMMEDIATE or DELAYED depending on whether it was defined as lazy
// 2) (because the fetch cannot be a JOIN...) do not push it to the stack
@ -564,10 +574,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
fetchOwner.buildAnyFetch(
attributeDefinition,
anyDefinition,
attributeDefinition.toAnyDefinition(),
fetchStrategy,
this
);
return false;
}
protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) {

View File

@ -25,7 +25,9 @@ package org.hibernate.loader.plan2.build.spi;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jboss.logging.Logger;
import org.jboss.logging.MDC;
@ -91,6 +93,8 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
private final ArrayDeque<ExpandingFetchSource> fetchSourceStack = new ArrayDeque<ExpandingFetchSource>();
private final Set<AttributeDefinition> pushedAttributes = new HashSet<AttributeDefinition>( );
protected AbstractLoadPlanBuildingAssociationVisitationStrategy(SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.querySpaces = new QuerySpacesImpl( sessionFactory );
@ -151,6 +155,7 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
propertyPathStack.pop();
MDC.remove( MDC_KEY );
fetchSourceStack.clear();
pushedAttributes.clear();
}
@ -198,6 +203,15 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
@Override
public void finishingEntity(EntityDefinition entityDefinition) {
final boolean isRoot = fetchSourceStack.size() == 1 && collectionReferenceStack.isEmpty();
if ( !isRoot ) {
return;
}
popEntityFromStack( entityDefinition );
}
private void popEntityFromStack(EntityDefinition entityDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this entity
final ExpandingFetchSource fetchSource = popFromStack();
@ -370,10 +384,19 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
@Override
public void finishingCollection(CollectionDefinition collectionDefinition) {
final boolean isRoot = fetchSourceStack.isEmpty() && collectionReferenceStack.size() == 1;
if ( !isRoot ) {
return;
}
popFromCollectionStack( collectionDefinition );
}
private void popFromCollectionStack(CollectionDefinition collectionDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this collection
final CollectionReference collectionReference = popFromCollectionStack();
if ( ! collectionReference.getCollectionPersister().equals( collectionDefinition.getCollectionPersister() ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
throw new WalkingException( "Mismatched CollectionReference from stack on pop" );
}
log.tracef(
@ -426,14 +449,17 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
return;
}
if ( indexType.isComponentType() ) {
if ( indexType.isEntityType() || indexType.isComponentType() ) {
// todo : validate the stack?
popFromStack();
final ExpandingFetchSource fetchSource = popFromStack();
if ( !CollectionFetchableIndex.class.isInstance( fetchSource ) ) {
throw new WalkingException(
"CollectionReference did not return an expected index graph : " +
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
}
// entity indexes would be popped during finishingEntity processing
log.tracef(
"%s Finished collection index graph : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ),
@ -484,19 +510,16 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
return;
}
if ( elementType.isComponentType() ) {
if ( elementType.isComponentType() || elementType.isAssociationType()) {
// pop it from the stack
final ExpandingFetchSource popped = popFromStack();
// validation
if ( ! CollectionFetchableElement.class.isInstance( popped ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
}
}
// entity indexes would be popped during finishingEntity processing
log.tracef(
"%s Finished collection element graph : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ),
@ -512,22 +535,22 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
compositionDefinition.getName()
);
if ( fetchSourceStack.isEmpty() ) {
if ( fetchSourceStack.isEmpty() && collectionReferenceStack.isEmpty() ) {
throw new HibernateException( "A component cannot be the root of a walk nor a graph" );
}
final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( compositionDefinition );
pushToStack( (ExpandingFetchSource) compositeFetch );
//final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( compositionDefinition );
//pushToStack( (ExpandingFetchSource) compositeFetch );
}
@Override
public void finishingComposite(CompositionDefinition compositionDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this composition
final ExpandingFetchSource popped = popFromStack();
//final ExpandingFetchSource popped = popFromStack();
if ( ! CompositeFetch.class.isInstance( popped ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
}
//if ( ! CompositeFetch.class.isInstance( popped ) ) {
// throw new WalkingException( "Mismatched FetchSource from stack on pop" );
//}
log.tracef(
"%s Finishing composite : %s",
@ -546,6 +569,7 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
final Type attributeType = attributeDefinition.getType();
final boolean isAnyType = attributeType.isAnyType();
final boolean isComponentType = attributeType.isComponentType();
final boolean isAssociationType = attributeType.isAssociationType();
final boolean isBasicType = ! ( isComponentType || isAssociationType );
@ -553,6 +577,11 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
if ( isBasicType ) {
return true;
}
else if ( isAnyType ) {
// If isAnyType is true, then isComponentType and isAssociationType will also be true
// so need to check isAnyType first so that it is handled properly.
return handleAnyAttribute( (AssociationAttributeDefinition) attributeDefinition );
}
else if ( isAssociationType ) {
return handleAssociationAttribute( (AssociationAttributeDefinition) attributeDefinition );
}
@ -563,6 +592,46 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
@Override
public void finishingAttribute(AttributeDefinition attributeDefinition) {
if ( pushedAttributes.contains( attributeDefinition ) ) {
final Type attributeType = attributeDefinition.getType();
if ( attributeType.isComponentType() ) {
// pop the current fetch owner, and make sure what we just popped represents this composition
final ExpandingFetchSource popped = popFromStack();
if ( ! CompositeFetch.class.isInstance( popped ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
}
}
else if ( attributeType.isAssociationType() ) {
final AssociationAttributeDefinition associationAttributeDefinition =
(AssociationAttributeDefinition) attributeDefinition;
if ( attributeType.isCollectionType() ) {
popFromCollectionStack( associationAttributeDefinition.toCollectionDefinition() );
}
else if ( attributeType.isEntityType() ) {
popEntityFromStack( associationAttributeDefinition.toEntityDefinition() );
}
else {
throw new WalkingException(
String.format(
"Unexpected attribute of type [%s] was pushed: %s",
associationAttributeDefinition.getType(),
associationAttributeDefinition
)
);
}
}
else {
throw new WalkingException(
String.format(
"Unexpected attribute of type [%s] was pushed: %s",
attributeDefinition.getType(),
attributeDefinition
)
);
}
pushedAttributes.remove( attributeDefinition );
}
log.tracef(
"%s Finishing up attribute : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ),
@ -759,7 +828,11 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
// }
@Override
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
public void foundAny(AnyMappingDefinition anyDefinition) {
// do nothing.
}
protected boolean handleAnyAttribute(AssociationAttributeDefinition attributeDefinition) {
// for ANY mappings we need to build a Fetch:
// 1) fetch type is SELECT, timing might be IMMEDIATE or DELAYED depending on whether it was defined as lazy
// 2) (because the fetch cannot be a JOIN...) do not push it to the stack
@ -774,12 +847,13 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
// fetchStrategy,
// this
// );
return false;
}
protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) {
// final ExpandingFetchSource currentSource = currentSource();
// final CompositeFetch fetch = currentSource.buildCompositeFetch( attributeDefinition, this );
// pushToStack( (ExpandingFetchSource) fetch );
final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( attributeDefinition );
pushToStack( (ExpandingFetchSource) compositeFetch );
pushedAttributes.add( attributeDefinition );
return true;
}
@ -814,6 +888,9 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
pushToCollectionStack( fetch );
}
}
if ( fetchStrategy.getStyle() == FetchStyle.JOIN ) {
pushedAttributes.add( attributeDefinition );
}
return fetchStrategy.getStyle() == FetchStyle.JOIN;
}

View File

@ -165,7 +165,7 @@ public interface AssociationVisitationStrategy {
*/
public void finishingAttribute(AttributeDefinition attributeDefinition);
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition);
public void foundAny(AnyMappingDefinition anyDefinition);
public void associationKeyRegistered(AssociationKey associationKey);
public FetchSource registeredFetchSource(AssociationKey associationKey);

View File

@ -128,12 +128,12 @@ public class MetamodelGraphWalker {
final EncapsulatedEntityIdentifierDefinition idAsEncapsulated = (EncapsulatedEntityIdentifierDefinition) identifierDefinition;
final AttributeDefinition idAttr = idAsEncapsulated.getAttributeDefinition();
if ( CompositionDefinition.class.isInstance( idAttr ) ) {
visitAttributes( (CompositionDefinition) idAttr );
visitCompositeDefinition( (CompositionDefinition) idAttr );
}
}
else {
// NonEncapsulatedEntityIdentifierDefinition itself is defined as a CompositionDefinition
visitAttributes( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
visitCompositeDefinition( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
}
strategy.finishingEntityIdentifier( identifierDefinition );
@ -196,7 +196,7 @@ public class MetamodelGraphWalker {
final AssociationAttributeDefinition.AssociationNature nature = attribute.getAssociationNature();
if ( nature == AssociationAttributeDefinition.AssociationNature.ANY ) {
visitAnyDefinition( attribute, attribute.toAnyDefinition() );
visitAnyDefinition( attribute.toAnyDefinition() );
}
else if ( nature == AssociationAttributeDefinition.AssociationNature.COLLECTION ) {
visitCollectionDefinition( attribute.toCollectionDefinition() );
@ -206,8 +206,8 @@ public class MetamodelGraphWalker {
}
}
private void visitAnyDefinition(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
strategy.foundAny( attributeDefinition, anyDefinition );
private void visitAnyDefinition(AnyMappingDefinition anyDefinition) {
strategy.foundAny( anyDefinition );
}
private void visitCompositeDefinition(CompositionDefinition compositionDefinition) {
@ -241,7 +241,7 @@ public class MetamodelGraphWalker {
try {
final Type collectionIndexType = collectionIndexDefinition.getType();
if ( collectionIndexType.isComponentType() ) {
visitAttributes( collectionIndexDefinition.toCompositeDefinition() );
visitCompositeDefinition( collectionIndexDefinition.toCompositeDefinition() );
}
else if ( collectionIndexType.isAssociationType() ) {
visitEntityDefinition( collectionIndexDefinition.toEntityDefinition() );
@ -259,7 +259,7 @@ public class MetamodelGraphWalker {
strategy.startingCollectionElements( elementDefinition );
if ( elementDefinition.getType().isComponentType() ) {
visitAttributes( elementDefinition.toCompositeElementDefinition() );
visitCompositeDefinition( elementDefinition.toCompositeElementDefinition() );
}
else if ( elementDefinition.getType().isEntityType() ) {
if ( ! collectionDefinition.getCollectionPersister().isOneToMany() ) {

View File

@ -230,7 +230,7 @@ public class LoggingAssociationVisitationStrategy implements AssociationVisitati
// }
@Override
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
public void foundAny(AnyMappingDefinition anyDefinition) {
// nothing to do
}