org.hibernate.boot.model.source.internal.hbm.EntityHierarchySourceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.boot.model.source.internal.hbm;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmEntityDiscriminatorType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmGeneratorSpecificationType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmMultiTenancyType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmPolymorphismEnum;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmRootEntityType;
import org.hibernate.boot.model.Caching;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.naming.EntityNaming;
import org.hibernate.boot.model.source.spi.DiscriminatorSource;
import org.hibernate.boot.model.source.spi.EntityHierarchySource;
import org.hibernate.boot.model.source.spi.EntityNamingSource;
import org.hibernate.boot.model.source.spi.IdentifierSource;
import org.hibernate.boot.model.source.spi.InheritanceType;
import org.hibernate.boot.model.source.spi.MultiTenancySource;
import org.hibernate.boot.model.source.spi.RelationalValueSource;
import org.hibernate.boot.model.source.spi.SizeSource;
import org.hibernate.boot.model.source.spi.VersionAttributeSource;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.internal.util.StringHelper;
/**
* Models an entity hierarchy as defined by {@code hbm.xml} documents
*
* @author Steve Ebersole
*/
public class EntityHierarchySourceImpl implements EntityHierarchySource {
private final RootEntitySourceImpl rootEntitySource;
private final IdentifierSource identifierSource;
private final VersionAttributeSource versionAttributeSource;
private final DiscriminatorSource discriminatorSource;
private final MultiTenancySource multiTenancySource;
private final Caching caching;
private final Caching naturalIdCaching;
private InheritanceType hierarchyInheritanceType = InheritanceType.NO_INHERITANCE;
private Set collectedEntityNames = new HashSet();
public EntityHierarchySourceImpl(RootEntitySourceImpl rootEntitySource) {
this.rootEntitySource = rootEntitySource;
this.rootEntitySource.injectHierarchy( this );
this.identifierSource = interpretIdentifierSource( rootEntitySource );
this.versionAttributeSource = interpretVersionSource( rootEntitySource );
this.discriminatorSource = interpretDiscriminatorSource( rootEntitySource );
this.multiTenancySource = interpretMultiTenancySource( rootEntitySource );
this.caching = Helper.createCaching( entityElement().getCache() );
this.naturalIdCaching = Helper.createNaturalIdCaching(
rootEntitySource.jaxbEntityMapping().getNaturalIdCache()
);
collectedEntityNames.add( rootEntitySource.getEntityNamingSource().getEntityName() );
}
private static IdentifierSource interpretIdentifierSource(RootEntitySourceImpl rootEntitySource) {
if ( rootEntitySource.jaxbEntityMapping().getId() == null
&& rootEntitySource.jaxbEntityMapping().getCompositeId() == null ) {
throw new MappingException(
String.format(
Locale.ENGLISH,
"Entity [%s] did not define an identifier",
rootEntitySource.getEntityNamingSource().getEntityName()
),
rootEntitySource.origin()
);
}
if ( rootEntitySource.jaxbEntityMapping().getId() != null ) {
return new IdentifierSourceSimpleImpl( rootEntitySource );
}
else {
// if we get here, we should have a composite identifier. Just need
// to determine if it is aggregated, or non-aggregated...
if ( StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getName() ) ) {
if ( rootEntitySource.jaxbEntityMapping().getCompositeId().isMapped()
&& StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getClazz() ) ) {
throw new MappingException(
"mapped composite identifier must name component class to use.",
rootEntitySource.origin()
);
}
return new IdentifierSourceNonAggregatedCompositeImpl( rootEntitySource );
}
else {
if ( rootEntitySource.jaxbEntityMapping().getCompositeId().isMapped() ) {
throw new MappingException(
"cannot combine mapped=\"true\" with specified name",
rootEntitySource.origin()
);
}
return new IdentifierSourceAggregatedCompositeImpl( rootEntitySource );
}
}
}
private static VersionAttributeSource interpretVersionSource(RootEntitySourceImpl rootEntitySource) {
final JaxbHbmRootEntityType entityElement = rootEntitySource.jaxbEntityMapping();
if ( entityElement.getVersion() != null ) {
return new VersionAttributeSourceImpl(
rootEntitySource.sourceMappingDocument(),
rootEntitySource,
entityElement.getVersion()
);
}
else if ( entityElement.getTimestamp() != null ) {
return new TimestampAttributeSourceImpl(
rootEntitySource.sourceMappingDocument(),
rootEntitySource,
entityElement.getTimestamp()
);
}
return null;
}
private static DiscriminatorSource interpretDiscriminatorSource(final RootEntitySourceImpl rootEntitySource) {
final JaxbHbmEntityDiscriminatorType jaxbDiscriminatorMapping =
rootEntitySource.jaxbEntityMapping().getDiscriminator();
if ( jaxbDiscriminatorMapping == null ) {
return null;
}
final RelationalValueSource relationalValueSource = RelationalValueSourceHelper.buildValueSource(
rootEntitySource.sourceMappingDocument(),
null,
new RelationalValueSourceHelper.AbstractColumnsAndFormulasSource() {
@Override
public XmlElementMetadata getSourceType() {
return XmlElementMetadata.DISCRIMINATOR;
}
@Override
public String getSourceName() {
return null;
}
@Override
public SizeSource getSizeSource() {
return Helper.interpretSizeSource(
jaxbDiscriminatorMapping.getLength(),
(Integer) null,
null
);
}
@Override
public String getFormulaAttribute() {
return jaxbDiscriminatorMapping.getFormulaAttribute();
}
@Override
public String getColumnAttribute() {
return jaxbDiscriminatorMapping.getColumnAttribute();
}
private List columnOrFormulas;
@Override
public List getColumnOrFormulaElements() {
if ( columnOrFormulas == null ) {
if ( jaxbDiscriminatorMapping.getColumn() != null ) {
if ( jaxbDiscriminatorMapping.getFormula() != null ) {
throw new MappingException(
String.format(
Locale.ENGLISH,
"discriminator mapping [%s] named both and , but only one or other allowed",
rootEntitySource.getEntityNamingSource().getEntityName()
),
rootEntitySource.sourceMappingDocument().getOrigin()
);
}
else {
columnOrFormulas = Collections.singletonList( jaxbDiscriminatorMapping.getColumn() );
}
}
else {
if ( jaxbDiscriminatorMapping.getFormula() != null ) {
columnOrFormulas = Collections.singletonList( jaxbDiscriminatorMapping.getFormula() );
}
else {
columnOrFormulas = Collections.emptyList();
}
}
}
return columnOrFormulas;
}
@Override
public Boolean isNullable() {
return !jaxbDiscriminatorMapping.isNotNull();
}
}
);
return new DiscriminatorSource() {
@Override
public EntityNaming getEntityNaming() {
return rootEntitySource.getEntityNamingSource();
}
@Override
public MetadataBuildingContext getBuildingContext() {
return rootEntitySource.metadataBuildingContext();
}
@Override
public RelationalValueSource getDiscriminatorRelationalValueSource() {
return relationalValueSource;
}
@Override
public String getExplicitHibernateTypeName() {
return jaxbDiscriminatorMapping.getType();
}
@Override
public boolean isForced() {
return jaxbDiscriminatorMapping.isForce();
}
@Override
public boolean isInserted() {
return jaxbDiscriminatorMapping.isInsert();
}
};
}
private static MultiTenancySource interpretMultiTenancySource(final RootEntitySourceImpl rootEntitySource) {
final JaxbHbmMultiTenancyType jaxbMultiTenancy = rootEntitySource.jaxbEntityMapping().getMultiTenancy();
if ( jaxbMultiTenancy == null ) {
return null;
}
final RelationalValueSource relationalValueSource = RelationalValueSourceHelper.buildValueSource(
rootEntitySource.sourceMappingDocument(),
null,
new RelationalValueSourceHelper.AbstractColumnsAndFormulasSource() {
@Override
public XmlElementMetadata getSourceType() {
return XmlElementMetadata.MULTI_TENANCY;
}
@Override
public String getSourceName() {
return null;
}
@Override
public String getFormulaAttribute() {
return jaxbMultiTenancy.getFormulaAttribute();
}
@Override
public String getColumnAttribute() {
return jaxbMultiTenancy.getColumnAttribute();
}
private List columnOrFormulas;
@Override
public List getColumnOrFormulaElements() {
if ( columnOrFormulas == null ) {
if ( jaxbMultiTenancy.getColumn() != null ) {
if ( jaxbMultiTenancy.getFormula() != null ) {
throw new MappingException(
String.format(
Locale.ENGLISH,
"discriminator mapping [%s] named both and , but only one or other allowed",
rootEntitySource.getEntityNamingSource().getEntityName()
),
rootEntitySource.sourceMappingDocument().getOrigin()
);
}
else {
columnOrFormulas = Collections.singletonList( jaxbMultiTenancy.getColumn() );
}
}
else {
if ( jaxbMultiTenancy.getFormula() != null ) {
columnOrFormulas = Collections.singletonList( jaxbMultiTenancy.getColumn() );
}
else {
columnOrFormulas = Collections.emptyList();
}
}
}
return columnOrFormulas;
}
@Override
public Boolean isNullable() {
return false;
}
}
);
return new MultiTenancySource() {
@Override
public RelationalValueSource getRelationalValueSource() {
return relationalValueSource;
}
@Override
public boolean isShared() {
return jaxbMultiTenancy.isShared();
}
@Override
public boolean bindAsParameter() {
return jaxbMultiTenancy.isBindAsParam();
}
};
}
@Override
public InheritanceType getHierarchyInheritanceType() {
return hierarchyInheritanceType;
}
@Override
public RootEntitySourceImpl getRoot() {
return rootEntitySource;
}
public void processSubclass(SubclassEntitySourceImpl subclassEntitySource) {
final InheritanceType inheritanceType = Helper.interpretInheritanceType( subclassEntitySource.jaxbEntityMapping() );
if ( hierarchyInheritanceType == InheritanceType.NO_INHERITANCE ) {
hierarchyInheritanceType = inheritanceType;
}
else if ( hierarchyInheritanceType != inheritanceType ) {
throw new MappingException( "Mixed inheritance strategies not supported", subclassEntitySource.getOrigin() );
}
collectedEntityNames.add( subclassEntitySource.getEntityNamingSource().getEntityName() );
}
protected JaxbHbmRootEntityType entityElement() {
return rootEntitySource.jaxbEntityMapping();
}
@Override
public IdentifierSource getIdentifierSource() {
return identifierSource;
}
@Override
public VersionAttributeSource getVersionAttributeSource() {
return versionAttributeSource;
}
@Override
public EntityMode getEntityMode() {
return rootEntitySource.determineEntityMode();
}
@Override
public boolean isMutable() {
return entityElement().isMutable();
}
@Override
public boolean isExplicitPolymorphism() {
return JaxbHbmPolymorphismEnum.EXPLICIT == entityElement().getPolymorphism();
}
@Override
public String getWhere() {
return entityElement().getWhere();
}
@Override
public String getRowId() {
return entityElement().getRowid();
}
@Override
public OptimisticLockStyle getOptimisticLockStyle() {
return entityElement().getOptimisticLock();
}
@Override
public Caching getCaching() {
return caching;
}
@Override
public Caching getNaturalIdCaching() {
return naturalIdCaching;
}
@Override
public DiscriminatorSource getDiscriminatorSource() {
return discriminatorSource;
}
@Override
public MultiTenancySource getMultiTenancySource() {
return multiTenancySource;
}
/**
* Package-protected to allow IdentifierSource implementations to access it.
*
* @param mappingDocument The source mapping document
* @param entityNaming The entity naming
* @param jaxbGeneratorMapping The identifier generator mapping
*
* @return The collected information.
*/
static IdentifierGeneratorDefinition interpretGeneratorDefinition(
MappingDocument mappingDocument,
EntityNamingSource entityNaming,
JaxbHbmGeneratorSpecificationType jaxbGeneratorMapping) {
if ( jaxbGeneratorMapping == null ) {
return null;
}
final String generatorName = jaxbGeneratorMapping.getClazz();
IdentifierGeneratorDefinition identifierGeneratorDefinition = mappingDocument.getMetadataCollector()
.getIdentifierGenerator( generatorName );
if ( identifierGeneratorDefinition == null ) {
identifierGeneratorDefinition = new IdentifierGeneratorDefinition(
entityNaming.getEntityName() + '.' + generatorName,
generatorName,
Helper.extractParameters( jaxbGeneratorMapping.getConfigParameters() )
);
}
return identifierGeneratorDefinition;
}
public Set getContainedEntityNames() {
return collectedEntityNames;
}
}