HHH-8056 : Create EntityHierarchyHelper to handle processing an EntityHierarchy
This commit is contained in:
parent
9a02c9e52d
commit
c0fa63579b
|
@ -227,6 +227,9 @@ public class Binder {
|
||||||
/**
|
/**
|
||||||
* The entry point of {@linkplain Binder} class, adds all the entity hierarchy one by one.
|
* The entry point of {@linkplain Binder} class, adds all the entity hierarchy one by one.
|
||||||
*
|
*
|
||||||
|
* Indexes all {@link EntitySource} objects in an {@link EntityHierarchy} and
|
||||||
|
* creates all {@link EntityBinding}.
|
||||||
|
*
|
||||||
* @param entityHierarchies The entity hierarchies resolved from mappings
|
* @param entityHierarchies The entity hierarchies resolved from mappings
|
||||||
*/
|
*/
|
||||||
public void addEntityHierarchies(final Iterable<EntityHierarchy> entityHierarchies) {
|
public void addEntityHierarchies(final Iterable<EntityHierarchy> entityHierarchies) {
|
||||||
|
@ -250,31 +253,45 @@ public class Binder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindEntityHierarchies() {
|
public void bindEntityHierarchies() {
|
||||||
|
// Bind everything except for (non-ID) attributes.
|
||||||
|
// Need to bind ID attributes before resolving associations.
|
||||||
|
// TODO: when we know the proper order for processing entity hierarchies,
|
||||||
|
// then applyToAllEntityHierarchies(...) can replace the following method.
|
||||||
bindEntityHierarchiesExcludingNonIdAttributeBindings();
|
bindEntityHierarchiesExcludingNonIdAttributeBindings();
|
||||||
|
|
||||||
// cannot resolve associations until after entity identifiers are defined.
|
// Resolve associations:
|
||||||
|
// - determine if JPA @OneToOne translates to Hibernate's one-to-one or unique many-to-one;
|
||||||
|
// - determine if JPA @OneToMany translates to Hibernate's one-to-many or unique many-to-many.
|
||||||
applyToAllEntityHierarchies( resolveAssociationSourcesExecutor() );
|
applyToAllEntityHierarchies( resolveAssociationSourcesExecutor() );
|
||||||
|
|
||||||
|
// At this point, SourceIndex has all necessary information.
|
||||||
|
|
||||||
|
// Bind all composite attribute containers. This excludes composite sub-attributes.
|
||||||
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.COMPOSITE ) );
|
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.COMPOSITE ) );
|
||||||
|
|
||||||
// bind singular attributes
|
// bind basic singular attributes, including composite sub-attributes that are basic.
|
||||||
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.BASIC ) );
|
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.BASIC ) );
|
||||||
// do many-to-one before one-to-one
|
|
||||||
|
// many-to-one needs to be bound before one-to-one (um, can't remember why).
|
||||||
|
|
||||||
|
// bind many-to-one attributes, including composite sub-attributes that are many-to-one.
|
||||||
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.MANY_TO_ONE ) );
|
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.MANY_TO_ONE ) );
|
||||||
|
|
||||||
|
// bind one-to-one attributes, including composite sub-attributes that are one-to-one.
|
||||||
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.ONE_TO_ONE ) );
|
applyToAllEntityHierarchies( bindSingularAttributesExecutor( SingularAttributeSource.Nature.ONE_TO_ONE ) );
|
||||||
|
|
||||||
// bind plural attributes (non-mappedBy first).
|
// bind plural attributes (non-mappedBy first), including composite sub-attributes that are plural
|
||||||
applyToAllEntityHierarchies( bindPluralAttributesExecutor( false ) );
|
applyToAllEntityHierarchies( bindPluralAttributesExecutor( false ) );
|
||||||
applyToAllEntityHierarchies( bindPluralAttributesExecutor( true ) );
|
applyToAllEntityHierarchies( bindPluralAttributesExecutor( true ) );
|
||||||
|
|
||||||
// Bind unique constraints after all attributes have been bound.
|
// Bind unique constraints after all attributes have been bound and the
|
||||||
// TODO: Add impl note about why...
|
// columns used by attributes is already determined.
|
||||||
applyToAllEntityHierarchies( bindUniqueConstraintsExecutor() );
|
applyToAllEntityHierarchies( bindUniqueConstraintsExecutor() );
|
||||||
|
|
||||||
// TODO: check if any many-to-one attribute bindings with logicalOneToOne == false have all columns
|
// TODO: check if any many-to-one attribute bindings with logicalOneToOne == false have all columns
|
||||||
// (and no formulas) contained in a defined unique key that only contains these columns.
|
// (and no formulas) contained in a defined unique key that only contains these columns.
|
||||||
// if so, mark the many-to-one as a logical one-to-one.
|
// if so, mark the many-to-one as a logical one-to-one.
|
||||||
|
// TODO: when does this have to be done.
|
||||||
}
|
}
|
||||||
|
|
||||||
private InheritanceType inheritanceType() {
|
private InheritanceType inheritanceType() {
|
||||||
|
@ -336,6 +353,10 @@ public class Binder {
|
||||||
bindSecondaryTables( entityBinding, entitySource );
|
bindSecondaryTables( entityBinding, entitySource );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// TODO: need to determine the proper order for processing EntityHierarchy objects
|
||||||
|
// so that dependent EntityHierarchy is processed after the EntityHierarchy it
|
||||||
|
// is dependent on.
|
||||||
|
// For now, just delay processing the dependent entity hierarchies.
|
||||||
Set<EntityHierarchy> unresolvedEntityHierarchies = new HashSet<EntityHierarchy>( );
|
Set<EntityHierarchy> unresolvedEntityHierarchies = new HashSet<EntityHierarchy>( );
|
||||||
for ( final EntityHierarchy entityHierarchy : entityHierarchiesByRootEntityName.values() ) {
|
for ( final EntityHierarchy entityHierarchy : entityHierarchiesByRootEntityName.values() ) {
|
||||||
if ( isIdentifierDependentOnOtherEntityHierarchy( entityHierarchy ) ) {
|
if ( isIdentifierDependentOnOtherEntityHierarchy( entityHierarchy ) ) {
|
||||||
|
@ -346,6 +367,11 @@ public class Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following is to try to resolve any dependent entity hierarchies.
|
||||||
|
// It runs through all the dependent entity hierarchies and resolves what it can.
|
||||||
|
// This process repeats until no more can be resolved.
|
||||||
|
// TODO: this will not be necessary once we know the proper order for
|
||||||
|
// processing entity hierarchies.
|
||||||
int oldSize = Integer.MAX_VALUE;
|
int oldSize = Integer.MAX_VALUE;
|
||||||
while( !unresolvedEntityHierarchies.isEmpty() && unresolvedEntityHierarchies.size() < oldSize ) {
|
while( !unresolvedEntityHierarchies.isEmpty() && unresolvedEntityHierarchies.size() < oldSize ) {
|
||||||
oldSize = unresolvedEntityHierarchies.size();
|
oldSize = unresolvedEntityHierarchies.size();
|
||||||
|
@ -361,11 +387,14 @@ public class Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If any entity hierarchies cannot be resolved, then throw exception.
|
||||||
if ( ! unresolvedEntityHierarchies.isEmpty() ) {
|
if ( ! unresolvedEntityHierarchies.isEmpty() ) {
|
||||||
throw new IllegalStateException( "could not resolve all EntityHierarchies." );
|
throw new IllegalStateException( "could not resolve all EntityHierarchies." );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this will not be necessary once we know the proper order for
|
||||||
|
// processing entity hierarchies.
|
||||||
private boolean isIdentifierDependentOnOtherEntityHierarchy(EntityHierarchy entityHierarchy) {
|
private boolean isIdentifierDependentOnOtherEntityHierarchy(EntityHierarchy entityHierarchy) {
|
||||||
final RootEntitySource rootEntitySource = entityHierarchy.getRootEntitySource();
|
final RootEntitySource rootEntitySource = entityHierarchy.getRootEntitySource();
|
||||||
final IdentifierSource identifierSource = rootEntitySource.getIdentifierSource();
|
final IdentifierSource identifierSource = rootEntitySource.getIdentifierSource();
|
||||||
|
@ -381,6 +410,8 @@ public class Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this will not be necessary once we know the proper order for
|
||||||
|
// processing entity hierarchies.
|
||||||
private boolean containsSingularAssociation(List<? extends AttributeSource> subAttributeSources) {
|
private boolean containsSingularAssociation(List<? extends AttributeSource> subAttributeSources) {
|
||||||
for ( AttributeSource attributeSource : subAttributeSources ) {
|
for ( AttributeSource attributeSource : subAttributeSources ) {
|
||||||
SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource;
|
SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource;
|
||||||
|
@ -424,9 +455,11 @@ public class Binder {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: create separate methods that are more clear for the cases.
|
||||||
private void bindSingularAttributes(
|
private void bindSingularAttributes(
|
||||||
final EntityBinding entityBinding,
|
final EntityBinding entityBinding,
|
||||||
final SingularAttributeSource.Nature nature) {
|
final SingularAttributeSource.Nature nature) {
|
||||||
|
// Get the map of all attributes for the entity binding of the specified nature.
|
||||||
Map<SourceIndex.AttributeSourceKey, SingularAttributeSource> map = sourceIndex.getSingularAttributeSources(
|
Map<SourceIndex.AttributeSourceKey, SingularAttributeSource> map = sourceIndex.getSingularAttributeSources(
|
||||||
entityBinding.getEntityName(),
|
entityBinding.getEntityName(),
|
||||||
nature
|
nature
|
||||||
|
@ -437,6 +470,7 @@ public class Binder {
|
||||||
final AttributeBindingContainer attributeBindingContainer =
|
final AttributeBindingContainer attributeBindingContainer =
|
||||||
locateAttributeBindingContainer( entityBinding, attributeSourceKey.containerPath() );
|
locateAttributeBindingContainer( entityBinding, attributeSourceKey.containerPath() );
|
||||||
if ( nature == SingularAttributeSource.Nature.COMPOSITE ) {
|
if ( nature == SingularAttributeSource.Nature.COMPOSITE ) {
|
||||||
|
// This only creates the composite attribute container.
|
||||||
createAggregatedCompositeAttribute(
|
createAggregatedCompositeAttribute(
|
||||||
attributeBindingContainer,
|
attributeBindingContainer,
|
||||||
(ComponentAttributeSource) attributeSource,
|
(ComponentAttributeSource) attributeSource,
|
||||||
|
@ -457,35 +491,45 @@ public class Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// The container is the EntityBinding itself.
|
||||||
bindAttribute( attributeBindingContainer, attributeSource );
|
bindAttribute( attributeBindingContainer, attributeSource );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All sub-attributes must be bound before it's type and ComponentMetamodel can be determined.
|
||||||
private void completeCompositeAttributeBindingIfPossible(
|
private void completeCompositeAttributeBindingIfPossible(
|
||||||
CompositeAttributeBinding compositeAttributeBinding,
|
CompositeAttributeBinding compositeAttributeBinding,
|
||||||
ComponentAttributeSource compositeAttributeSource
|
ComponentAttributeSource compositeAttributeSource
|
||||||
) {
|
) {
|
||||||
|
// Find out the number of sub-attributes, excluding the parent attribute.
|
||||||
final int nAttributeSourcesExcludingParent =
|
final int nAttributeSourcesExcludingParent =
|
||||||
compositeAttributeBinding.getParentReference() != null ?
|
compositeAttributeBinding.getParentReference() != null ?
|
||||||
compositeAttributeSource.attributeSources().size() - 1 :
|
compositeAttributeSource.attributeSources().size() - 1 :
|
||||||
compositeAttributeSource.attributeSources().size();
|
compositeAttributeSource.attributeSources().size();
|
||||||
if ( compositeAttributeBinding.attributeBindingSpan() == nAttributeSourcesExcludingParent ) {
|
if ( compositeAttributeBinding.attributeBindingSpan() == nAttributeSourcesExcludingParent ) {
|
||||||
|
// All sub-attribute bindings are present; now check if all sub-attributes have
|
||||||
|
// their type resolved.
|
||||||
boolean allResolved = true;
|
boolean allResolved = true;
|
||||||
for ( AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) {
|
for ( AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) {
|
||||||
if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() == null ) {
|
if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() == null ) {
|
||||||
|
// Something is not resolved.
|
||||||
allResolved = false;
|
allResolved = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( allResolved ) {
|
if ( allResolved ) {
|
||||||
|
// All are resolved, so we can bind the type.
|
||||||
typeHelper.bindAggregatedCompositeAttributeType(
|
typeHelper.bindAggregatedCompositeAttributeType(
|
||||||
false,
|
false,
|
||||||
(Aggregate) compositeAttributeBinding.getAttribute().getSingularAttributeType(),
|
(Aggregate) compositeAttributeBinding.getAttribute().getSingularAttributeType(),
|
||||||
null, // TODO: don't have the default value at this point; shouldn't be needed...
|
null, // TODO: don't have the default value at this point; shouldn't be needed...
|
||||||
compositeAttributeBinding
|
compositeAttributeBinding
|
||||||
);
|
);
|
||||||
|
// Now check the container.
|
||||||
if ( compositeAttributeBinding.getContainer() instanceof CompositeAttributeBindingContainer ) {
|
if ( compositeAttributeBinding.getContainer() instanceof CompositeAttributeBindingContainer ) {
|
||||||
|
// The container is also a CompositeAttributeBindingContainer.
|
||||||
|
// We need this process for the container.
|
||||||
final CompositeAttributeBinding parentCompositeAttributeBinding =
|
final CompositeAttributeBinding parentCompositeAttributeBinding =
|
||||||
(CompositeAttributeBinding) compositeAttributeBinding.seekEntityBinding().locateAttributeBinding(
|
(CompositeAttributeBinding) compositeAttributeBinding.seekEntityBinding().locateAttributeBinding(
|
||||||
( compositeAttributeBinding.getContainer() ).getPathBase()
|
( compositeAttributeBinding.getContainer() ).getPathBase()
|
||||||
|
@ -517,10 +561,12 @@ public class Binder {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: may want bind plural attributes of a particular element nature.
|
||||||
private void bindPluralAttributes(
|
private void bindPluralAttributes(
|
||||||
final EntityBinding entityBinding,
|
final EntityBinding entityBinding,
|
||||||
final EntitySource entitySource,
|
final EntitySource entitySource,
|
||||||
final boolean isInverse) {
|
final boolean isInverse) {
|
||||||
|
// Get the map for inverse or non-inverse (as specified) plural attributes
|
||||||
Map<SourceIndex.AttributeSourceKey, PluralAttributeSource> map = sourceIndex.getPluralAttributeSources(
|
Map<SourceIndex.AttributeSourceKey, PluralAttributeSource> map = sourceIndex.getPluralAttributeSources(
|
||||||
entityBinding.getEntityName(),
|
entityBinding.getEntityName(),
|
||||||
isInverse
|
isInverse
|
||||||
|
@ -528,16 +574,19 @@ public class Binder {
|
||||||
for ( Map.Entry<SourceIndex.AttributeSourceKey, PluralAttributeSource> entry : map.entrySet() ){
|
for ( Map.Entry<SourceIndex.AttributeSourceKey, PluralAttributeSource> entry : map.entrySet() ){
|
||||||
final SourceIndex.AttributeSourceKey attributeSourceKey = entry.getKey();
|
final SourceIndex.AttributeSourceKey attributeSourceKey = entry.getKey();
|
||||||
final PluralAttributeSource attributeSource = entry.getValue();
|
final PluralAttributeSource attributeSource = entry.getValue();
|
||||||
|
// Bind the attribute into the appropriate container.
|
||||||
final AttributeBindingContainer attributeBindingContainer =
|
final AttributeBindingContainer attributeBindingContainer =
|
||||||
locateAttributeBindingContainer( entityBinding, attributeSourceKey.containerPath() );
|
locateAttributeBindingContainer( entityBinding, attributeSourceKey.containerPath() );
|
||||||
bindAttribute( attributeBindingContainer, attributeSource );
|
bindAttribute( attributeBindingContainer, attributeSource );
|
||||||
if ( attributeBindingContainer instanceof CompositeAttributeBinding ) {
|
if ( attributeBindingContainer instanceof CompositeAttributeBinding ) {
|
||||||
|
// We just bound a sub-attribute into a CompositeAttributeBinding.
|
||||||
final CompositeAttributeBinding compositeAttributeBinding = (CompositeAttributeBinding) attributeBindingContainer;
|
final CompositeAttributeBinding compositeAttributeBinding = (CompositeAttributeBinding) attributeBindingContainer;
|
||||||
final ComponentAttributeSource compositeAttributeSource =
|
final ComponentAttributeSource compositeAttributeSource =
|
||||||
(ComponentAttributeSource) sourceIndex.attributeSource(
|
(ComponentAttributeSource) sourceIndex.attributeSource(
|
||||||
entityBinding.getEntityName(),
|
entityBinding.getEntityName(),
|
||||||
compositeAttributeBinding.getPathBase()
|
compositeAttributeBinding.getPathBase()
|
||||||
);
|
);
|
||||||
|
// Resolve the type if types are resolved for all sub-attributes now.
|
||||||
completeCompositeAttributeBindingIfPossible( compositeAttributeBinding, compositeAttributeSource );
|
completeCompositeAttributeBindingIfPossible( compositeAttributeBinding, compositeAttributeSource );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,10 @@ public class EntityHierarchyHelper {
|
||||||
* Apply executors to a single entity hierarchy.
|
* Apply executors to a single entity hierarchy.
|
||||||
*
|
*
|
||||||
* @param entityHierarchy The entity hierarchy to be binded.
|
* @param entityHierarchy The entity hierarchy to be binded.
|
||||||
|
* @param rootEntityExecutor The executor to be applied to the root {@link EntitySource}
|
||||||
|
* in the entity hierarchy.
|
||||||
|
* @param subEntityExecutor The executer to be applied to each {@link SubclassEntitySource}
|
||||||
|
* in the entity hierarchy.
|
||||||
*/
|
*/
|
||||||
public void applyToEntityHierarchy(
|
public void applyToEntityHierarchy(
|
||||||
final EntityHierarchy entityHierarchy,
|
final EntityHierarchy entityHierarchy,
|
||||||
|
|
|
@ -473,6 +473,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
|
|
||||||
private void processMappings(MetadataSourceProcessor[] metadataSourceProcessors) {
|
private void processMappings(MetadataSourceProcessor[] metadataSourceProcessors) {
|
||||||
final Binder binder = new Binder( this, identifierGeneratorFactory );
|
final Binder binder = new Binder( this, identifierGeneratorFactory );
|
||||||
|
// Add all hierarchies first, before binding.
|
||||||
for ( MetadataSourceProcessor processor : metadataSourceProcessors ) {
|
for ( MetadataSourceProcessor processor : metadataSourceProcessors ) {
|
||||||
binder.addEntityHierarchies( processor.extractEntityHierarchies() );
|
binder.addEntityHierarchies( processor.extractEntityHierarchies() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class SourceIndex {
|
||||||
|
|
||||||
private final Map<String, EntitySourceIndex> entitySourceIndexByEntityName = new HashMap<String, EntitySourceIndex>();
|
private final Map<String, EntitySourceIndex> entitySourceIndexByEntityName = new HashMap<String, EntitySourceIndex>();
|
||||||
private final Map<AttributeSourceKey, AttributeSource> attributeSourcesByKey = new HashMap<AttributeSourceKey, AttributeSource>();
|
private final Map<AttributeSourceKey, AttributeSource> attributeSourcesByKey = new HashMap<AttributeSourceKey, AttributeSource>();
|
||||||
private final Map<AttributeSourceKey, AttributeSourceKey> mappedByAttributeNamesByOwnerAttributeNames =
|
private final Map<AttributeSourceKey, AttributeSourceKey> mappedByAttributeKeysByOwnerAttributeKeys =
|
||||||
new HashMap<AttributeSourceKey, AttributeSourceKey>();
|
new HashMap<AttributeSourceKey, AttributeSourceKey>();
|
||||||
|
|
||||||
public void indexEntitySource(final EntitySource entitySource) {
|
public void indexEntitySource(final EntitySource entitySource) {
|
||||||
|
@ -98,7 +98,7 @@ public class SourceIndex {
|
||||||
|
|
||||||
public AttributeSource locateAttributeSourceOwnedBy(final String entityName, final String attributePath) {
|
public AttributeSource locateAttributeSourceOwnedBy(final String entityName, final String attributePath) {
|
||||||
AttributeSourceKey ownerKey = new AttributeSourceKey( entityName, attributePath );
|
AttributeSourceKey ownerKey = new AttributeSourceKey( entityName, attributePath );
|
||||||
AttributeSourceKey mappedByKey = mappedByAttributeNamesByOwnerAttributeNames.get( ownerKey );
|
AttributeSourceKey mappedByKey = mappedByAttributeKeysByOwnerAttributeKeys.get( ownerKey );
|
||||||
return mappedByKey == null ? null : attributeSourcesByKey.get( mappedByKey );
|
return mappedByKey == null ? null : attributeSourcesByKey.get( mappedByKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ public class SourceIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMappedByAssociationByOwnerAssociation(AttributeSourceKey ownerKey, AttributeSourceKey ownedKey) {
|
void addMappedByAssociationByOwnerAssociation(AttributeSourceKey ownerKey, AttributeSourceKey ownedKey) {
|
||||||
mappedByAttributeNamesByOwnerAttributeNames.put(
|
mappedByAttributeKeysByOwnerAttributeKeys.put(
|
||||||
ownerKey,
|
ownerKey,
|
||||||
ownedKey
|
ownedKey
|
||||||
);
|
);
|
||||||
|
@ -270,10 +270,12 @@ public class SourceIndex {
|
||||||
private final EntitySource entitySource;
|
private final EntitySource entitySource;
|
||||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> identifierAttributeSourcesByNature =
|
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> identifierAttributeSourcesByNature =
|
||||||
new HashMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>();
|
new HashMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>();
|
||||||
|
// TODO: split out inverse and non-inverse SingularAttributeSource maps.
|
||||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> singularAttributeSourcesByNature =
|
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> singularAttributeSourcesByNature =
|
||||||
new HashMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>();
|
new HashMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>();
|
||||||
// TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests
|
// TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests
|
||||||
// depend on the ordering
|
// depend on the ordering
|
||||||
|
// TODO: rework nonInversePluralAttributeSourcesByKey and inversePluralAttributeSourcesByKey
|
||||||
private final Map<AttributeSourceKey, PluralAttributeSource> nonInversePluralAttributeSourcesByKey =
|
private final Map<AttributeSourceKey, PluralAttributeSource> nonInversePluralAttributeSourcesByKey =
|
||||||
new LinkedHashMap<AttributeSourceKey, PluralAttributeSource>();
|
new LinkedHashMap<AttributeSourceKey, PluralAttributeSource>();
|
||||||
private final Map<AttributeSourceKey, PluralAttributeSource> inversePluralAttributeSourcesByKey =
|
private final Map<AttributeSourceKey, PluralAttributeSource> inversePluralAttributeSourcesByKey =
|
||||||
|
@ -364,16 +366,21 @@ public class SourceIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveAssociationSources(final EntityBinding entityBinding) {
|
private void resolveAssociationSources(final EntityBinding entityBinding) {
|
||||||
|
// Cycle through non-inverse plural attributes.
|
||||||
for ( Map.Entry<AttributeSourceKey,PluralAttributeSource> entry : inversePluralAttributeSourcesByKey.entrySet() ) {
|
for ( Map.Entry<AttributeSourceKey,PluralAttributeSource> entry : inversePluralAttributeSourcesByKey.entrySet() ) {
|
||||||
final AttributeSourceKey pluralAttributeSourceKey = entry.getKey();
|
final AttributeSourceKey pluralAttributeSourceKey = entry.getKey();
|
||||||
final PluralAttributeSource pluralAttributeSource = entry.getValue();
|
final PluralAttributeSource pluralAttributeSource = entry.getValue();
|
||||||
if ( pluralAttributeSource.getMappedBy() != null ) {
|
if ( pluralAttributeSource.getMappedBy() != null ) {
|
||||||
|
// This plural attribute is mappedBy the opposite side of the association,
|
||||||
|
// so it needs to be resolved.
|
||||||
|
// TODO: this should really just resolve PluralAttributeElementSource.Nature
|
||||||
pluralAttributeSource.resolvePluralAttributeElementSource(
|
pluralAttributeSource.resolvePluralAttributeElementSource(
|
||||||
new PluralAttributeElementSourceResolver.PluralAttributeElementSourceResolutionContext() {
|
new PluralAttributeElementSourceResolver.PluralAttributeElementSourceResolutionContext() {
|
||||||
@Override
|
@Override
|
||||||
public AttributeSource resolveAttributeSource(String referencedEntityName, String mappedBy) {
|
public AttributeSource resolveAttributeSource(String referencedEntityName, String mappedBy) {
|
||||||
AttributeSourceKey ownerAttributeSourceKey = new AttributeSourceKey( referencedEntityName, mappedBy );
|
AttributeSourceKey ownerAttributeSourceKey = new AttributeSourceKey( referencedEntityName, mappedBy );
|
||||||
AttributeSource ownerAttributeSource = sourceIndex.attributeSource( referencedEntityName, mappedBy );
|
AttributeSource ownerAttributeSource = sourceIndex.attributeSource( referencedEntityName, mappedBy );
|
||||||
|
// TODO: is this needed? if so, make more obvious and rename method.
|
||||||
sourceIndex.addMappedByAssociationByOwnerAssociation(
|
sourceIndex.addMappedByAssociationByOwnerAssociation(
|
||||||
ownerAttributeSourceKey,
|
ownerAttributeSourceKey,
|
||||||
pluralAttributeSourceKey
|
pluralAttributeSourceKey
|
||||||
|
@ -387,6 +394,8 @@ public class SourceIndex {
|
||||||
final Map<AttributeSourceKey,SingularAttributeSource> unresolvedSingularAttributeSourceMap =
|
final Map<AttributeSourceKey,SingularAttributeSource> unresolvedSingularAttributeSourceMap =
|
||||||
singularAttributeSourcesByNature.get( null );
|
singularAttributeSourcesByNature.get( null );
|
||||||
if ( unresolvedSingularAttributeSourceMap != null ) {
|
if ( unresolvedSingularAttributeSourceMap != null ) {
|
||||||
|
// cycle through unresolved SingularAttributeSource.
|
||||||
|
// TODO: rework so approach is similar to one-to-many/many-to-many resolution.
|
||||||
for ( Iterator<Map.Entry<AttributeSourceKey,SingularAttributeSource>> it = unresolvedSingularAttributeSourceMap.entrySet().iterator(); it.hasNext(); ) {
|
for ( Iterator<Map.Entry<AttributeSourceKey,SingularAttributeSource>> it = unresolvedSingularAttributeSourceMap.entrySet().iterator(); it.hasNext(); ) {
|
||||||
final Map.Entry<AttributeSourceKey,SingularAttributeSource> entry = it.next();
|
final Map.Entry<AttributeSourceKey,SingularAttributeSource> entry = it.next();
|
||||||
final AttributeSourceKey attributeSourceKey = entry.getKey();
|
final AttributeSourceKey attributeSourceKey = entry.getKey();
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
|
||||||
this.nature = associationAttribute.getPluralAttributeNature();
|
this.nature = associationAttribute.getPluralAttributeNature();
|
||||||
if ( associationAttribute.getMappedBy() == null ) {
|
if ( associationAttribute.getMappedBy() == null ) {
|
||||||
this.ownerAttributeSource = this;
|
this.ownerAttributeSource = this;
|
||||||
this.elementSource = determineOwnerElementSource( this, associationAttribute, entityClass );
|
this.elementSource = determineElementSource( this, associationAttribute, entityClass );
|
||||||
}
|
}
|
||||||
this.filterSources = determineFilterSources(associationAttribute);
|
this.filterSources = determineFilterSources(associationAttribute);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PluralAttributeElementSource determineOwnerElementSource(
|
private static PluralAttributeElementSource determineElementSource(
|
||||||
AttributeSource ownerAttributeSource,
|
AttributeSource ownerAttributeSource,
|
||||||
PluralAssociationAttribute associationAttribute,
|
PluralAssociationAttribute associationAttribute,
|
||||||
ConfiguredClass entityClass) {
|
ConfiguredClass entityClass) {
|
||||||
|
@ -353,18 +353,19 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
|
||||||
@Override
|
@Override
|
||||||
public PluralAttributeElementSource resolvePluralAttributeElementSource(
|
public PluralAttributeElementSource resolvePluralAttributeElementSource(
|
||||||
PluralAttributeElementSourceResolutionContext context) {
|
PluralAttributeElementSourceResolutionContext context) {
|
||||||
if ( associationAttribute.getMappedBy() == null ) {
|
if ( elementSource == null ) {
|
||||||
return elementSource;
|
// elementSource has not been initialized, so we need to resolve it using the
|
||||||
}
|
// association owner.
|
||||||
else {
|
// Get the owner attribute source that maps the opposite side of the association.
|
||||||
ownerAttributeSource = context.resolveAttributeSource(
|
ownerAttributeSource = context.resolveAttributeSource(
|
||||||
associationAttribute.getReferencedEntityType(),
|
associationAttribute.getReferencedEntityType(),
|
||||||
associationAttribute.getMappedBy()
|
associationAttribute.getMappedBy()
|
||||||
);
|
);
|
||||||
elementSource = determineOwnerElementSource( ownerAttributeSource, associationAttribute, entityClass );
|
// Initialize resolved entitySource.
|
||||||
|
elementSource = determineElementSource( ownerAttributeSource, associationAttribute, entityClass );
|
||||||
|
}
|
||||||
return elementSource;
|
return elementSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ public abstract class AbstractPluralAttributeSourceImpl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PluralAttributeElementSource resolvePluralAttributeElementSource(PluralAttributeElementSourceResolutionContext context) {
|
public PluralAttributeElementSource resolvePluralAttributeElementSource(PluralAttributeElementSourceResolutionContext context) {
|
||||||
|
// elementSource is already resolved; nothing to do.
|
||||||
return elementSource;
|
return elementSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue