/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* 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.ogm.persister.impl;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.MarkerObject;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Subclass;
import org.hibernate.ogm.util.impl.Log;
import org.hibernate.ogm.util.impl.LoggerFactory;
import org.hibernate.sql.InFragment;
import org.hibernate.type.DiscriminatorType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
/**
* The discriminator is a column containing a different value for each entity type.
*
* @author "Davide D'Alto" <davide@hibernate.org>
*/
class ColumnBasedDiscriminator implements EntityDiscriminator {
private static final Log log = LoggerFactory.make();
private static final Object NULL_DISCRIMINATOR = new MarkerObject( "<null discriminator>" );
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "<not null discriminator>" );
private final String alias;
private final String columnName;
private final Type discriminatorType;
private final boolean forced;
private final boolean needed;
private final String sqlValue;
private final Object value;
private final Map<Object, String> subclassesByValue;
public ColumnBasedDiscriminator(final PersistentClass persistentClass, final SessionFactoryImplementor factory, final Column column) {
forced = persistentClass.isForceDiscriminator();
columnName = column.getQuotedName( factory.getDialect() );
alias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
discriminatorType = persistentClass.getDiscriminator().getType() == null
? StringType.INSTANCE
: persistentClass.getDiscriminator().getType();
value = value( persistentClass, discriminatorType );
sqlValue = sqlValue( persistentClass, factory.getDialect(), value, discriminatorType );
subclassesByValue = subclassesByValue( persistentClass, value, discriminatorType );
needed = true;
}
private static Map<Object, String> subclassesByValue(final PersistentClass persistentClass, Object value, Type type) {
Map<Object, String> subclassesByDsicriminator = new HashMap<Object, String>();
subclassesByDsicriminator.put( value, persistentClass.getEntityName() );
if ( persistentClass.isPolymorphic() ) {
@SuppressWarnings("unchecked")
Iterator<Subclass> iter = persistentClass.getSubclassIterator();
while ( iter.hasNext() ) {
Subclass sc = iter.next();
subclassesByDsicriminator.put( value( sc, type ), sc.getEntityName() );
}
}
return subclassesByDsicriminator;
}
public static String sqlValue(PersistentClass persistentClass, Dialect dialect,
Object value, Type discriminatorType) {
try {
return obtainSqlValue( persistentClass, dialect, value, discriminatorType );
}
catch ( ClassCastException cce ) {
throw log.illegalDiscrimantorType( discriminatorType.getName() );
}
catch ( Exception e ) {
throw log.unableToConvertStringToDiscriminator( e );
}
}
private static String obtainSqlValue(PersistentClass persistentClass, Dialect dialect,
Object value, Type discriminatorType) throws Exception {
if ( persistentClass.isDiscriminatorValueNull() ) {
return InFragment.NULL;
}
if ( persistentClass.isDiscriminatorValueNotNull() ) {
return InFragment.NOT_NULL;
}
@SuppressWarnings("unchecked")
DiscriminatorType<Object> dtype = (DiscriminatorType<Object>) discriminatorType;
return dtype.objectToSQLString( value, dialect );
}
public static Object value(PersistentClass persistentClass, Type discriminatorType) {
try {
return obtainValue( persistentClass, discriminatorType );
}
catch ( ClassCastException cce ) {
throw log.illegalDiscrimantorType( discriminatorType.getName() );
}
catch ( Exception e ) {
throw log.unableToConvertStringToDiscriminator( e );
}
}
private static Object obtainValue(PersistentClass persistentClass, Type discriminatorType)
throws Exception {
if ( persistentClass.isDiscriminatorValueNull() ) {
return NULL_DISCRIMINATOR;
}
if ( persistentClass.isDiscriminatorValueNotNull() ) {
return NOT_NULL_DISCRIMINATOR;
}
@SuppressWarnings("unchecked")
DiscriminatorType<Object> dtype = (DiscriminatorType<Object>) discriminatorType;
return dtype.stringToObject( persistentClass.getDiscriminatorValue() );
}
@Override
public String provideClassByValue(Object value) {
return subclassesByValue.get( value );
}
@Override
public String getSqlValue() {
return sqlValue;
}
@Override
public String getColumnName() {
return columnName;
}
@Override
public String getAlias() {
return alias;
}
@Override
public Type getType() {
return discriminatorType;
}
@Override
public Object getValue() {
return value;
}
@Override
public boolean isForced() {
return forced;
}
@Override
public boolean isNeeded() {
return needed;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( "ColumnBasedDiscriminator [alias=" );
builder.append( alias );
builder.append( ", columnName=" );
builder.append( columnName );
builder.append( ", discriminatorType=" );
builder.append( discriminatorType );
builder.append( ", forced=" );
builder.append( forced );
builder.append( ", needed=" );
builder.append( needed );
builder.append( ", sqlValue=" );
builder.append( sqlValue );
builder.append( ", value=" );
builder.append( value );
builder.append( ", subclassByValue=" );
builder.append( subclassesByValue );
builder.append( "]" );
return builder.toString();
}
}