/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.persister.entity.internal;
import java.util.Iterator;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Value;
import org.hibernate.orm.persister.OrmTypeHelper;
import org.hibernate.orm.persister.common.internal.SingularAttributeBasic;
import org.hibernate.orm.persister.common.internal.SingularAttributeEmbedded;
import org.hibernate.orm.persister.common.internal.PersisterHelper;
import org.hibernate.orm.persister.common.spi.Column;
import org.hibernate.orm.persister.common.spi.Table;
import org.hibernate.orm.persister.entity.spi.EntityHierarchy;
import org.hibernate.orm.persister.entity.spi.EntityPersister;
import org.hibernate.orm.persister.entity.spi.IdentifierDescriptor;
import org.hibernate.orm.persister.entity.spi.InheritanceStrategy;
import org.hibernate.orm.persister.spi.PersisterCreationContext;
import org.hibernate.type.CompositeType;
/**
* @author Steve Ebersole
*/
public class EntityHierarchyImpl implements EntityHierarchy {
private final EntityPersister rootEntityPersister;
private IdentifierDescriptor identifierDescriptor;
public EntityHierarchyImpl(
PersisterCreationContext creationContext,
RootClass rootEntityBinding,
EntityPersister rootEntityPersister) {
this.rootEntityPersister = rootEntityPersister;
final Table identifierTable = resolveIdentifierTable( creationContext, rootEntityBinding );
this.identifierDescriptor = interpretIdentifierDescriptor(
this,
rootEntityPersister,
creationContext,
rootEntityBinding,
identifierTable
);
}
private static Table resolveIdentifierTable(
PersisterCreationContext creationContext,
RootClass rootEntityBinding) {
// final JdbcEnvironment jdbcEnvironment = creationContext.getSessionFactory()
// .getJdbcServices()
// .getJdbcEnvironment();
final org.hibernate.mapping.Table mappingTable = rootEntityBinding.getIdentityTable();
if ( mappingTable.getSubselect() != null ) {
return creationContext.getDatabaseModel().findDerivedTable( mappingTable.getSubselect() );
}
else {
// final String name = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
// mappingTable.getQualifiedTableName(),
// jdbcEnvironment.getDialect()
// );
final String name = mappingTable.getQualifiedTableName().render();
return creationContext.getDatabaseModel().findPhysicalTable( name );
}
}
private static IdentifierDescriptor interpretIdentifierDescriptor(
EntityHierarchyImpl hierarchy,
EntityPersister rootEntityPersister,
PersisterCreationContext creationContext,
RootClass rootEntityBinding,
Table identifierTable) {
final KeyValue identifierValueMapping = rootEntityBinding.getIdentifier();
final List<Column> idColumns = resolveColumns( identifierTable, identifierValueMapping, creationContext );
if ( identifierValueMapping.getType() instanceof org.hibernate.type.BasicType ) {
return new IdentifierDescriptorSimpleImpl(
hierarchy.getRootEntityPersister(),
rootEntityBinding.getIdentifierProperty().getName(),
OrmTypeHelper.convertBasic(
(org.hibernate.type.BasicType) identifierValueMapping.getType(),
creationContext.getTypeConfiguration()
),
idColumns
);
}
else {
final CompositeType cidType = (CompositeType) identifierValueMapping.getType();
// todo : need to pass along that any built sub attributes are part of the id
if ( rootEntityBinding.hasIdentifierProperty() ) {
return new IdentifierDescriptorAggregatedEmbeddedImpl(
(SingularAttributeEmbedded) PersisterHelper.INSTANCE.buildSingularAttribute(
creationContext,
// the declaring type...
/// for now we use the root entity
hierarchy.getRootEntityPersister(),
// value?
null,
rootEntityBinding.getIdentifierProperty().getName(),
OrmTypeHelper.convertComposite(
creationContext,
rootEntityBinding.getIdentifierProperty().getName(),
(Component) identifierValueMapping,
hierarchy.getRootEntityPersister(),
creationContext.getTypeConfiguration()
),
idColumns
)
);
}
else {
// todo : pass info about ther IdClass
return new IdentifierDescriptorNonAggregatedEmbeddedImpl(
rootEntityPersister,
OrmTypeHelper.convertComposite(
creationContext,
"<id>",
(Component) identifierValueMapping,
hierarchy.getRootEntityPersister(),
creationContext.getTypeConfiguration()
),
OrmTypeHelper.convertComposite(
creationContext,
"<IdClass>",
rootEntityBinding.getIdentifierMapper(),
hierarchy.getRootEntityPersister(),
creationContext.getTypeConfiguration()
)
);
// PersisterHelper.INSTANCE.buildEmbeddablePersister(
// creationContext,
// hierarchy.getRootEntityPersister(),
// rootEntityBinding.getEntityName() + ".id",
// cidType,
// idColumns
// )
}
}
}
private static List<Column> resolveColumns(
Table table,
Value value,
PersisterCreationContext creationContext) {
final String[] columnNames = new String[value.getColumnSpan()];
final String[] formulas = value.hasFormula() ? new String[value.getColumnSpan()] : null;
//final SqlTypeDescriptor[] sqlTypeDescriptors = new SqlTypeDescriptor[value.getColumnSpan()];
final int[] jdbcTypeCodes = new int[value.getColumnSpan()];
final Iterator<Selectable> itr = value.getColumnIterator();
int i = 0;
while ( itr.hasNext() ) {
final Selectable selectable = itr.next();
if ( selectable instanceof org.hibernate.mapping.Column ) {
// columnNames[i] = ( (org.hibernate.mapping.Column) selectable ).getQuotedName(
// creationContext.getSessionFactory().getJdbcServices().getJdbcEnvironment().getDialect()
// );
columnNames[i] = '`' + ( (org.hibernate.mapping.Column) selectable ).getName() + '`';
}
else {
if ( formulas == null ) {
throw new HibernateException(
"Value indicated it does not have formulas, but a formula was encountered : " + selectable );
}
formulas[i] = ( (Formula) selectable ).getFormula();
}
// todo : need access to the TypeConfiguration...
//sqlTypeDescriptors[i] = creationContext.getSessionFactory()
jdbcTypeCodes[i] = value.getType().sqlTypes( null )[i];
// todo : keep track of readers/writers... how exactly?
// something like this vv ?
// Column#applyReadExpression( col.getReadExpr( dialect ) )
// Column#applyWriteExpression( col.getWriteExpr() )
i++;
}
// makeColumns(
// creationContext,
// tableSelector,
// columnNames,
// formulas,
// sqlTypeDescriptors (or just JDBC type codes?)
// )
return PersisterHelper.makeValues(
creationContext,
// todo : a Table "selector"...
table,
columnNames,
formulas,
jdbcTypeCodes
);
}
@Override
public EntityPersister getRootEntityPersister() {
return rootEntityPersister;
}
@Override
public InheritanceStrategy getInheritanceStrategy() {
return InheritanceStrategy.NONE;
}
@Override
public IdentifierDescriptor getIdentifierDescriptor() {
return identifierDescriptor;
}
@Override
public SingularAttributeBasic getVersionAttribute() {
return null;
}
@Override
public void finishInitialization(PersisterCreationContext creationContext, RootClass mappingType) {
// todo : identifierDescriptor init, etc
}
}