package org.hibernate.type.descriptor.sql;
import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.jboss.logging.Logger;
public class SqlTypeDescriptorRegistry {
public static final SqlTypeDescriptorRegistry INSTANCE = new SqlTypeDescriptorRegistry();
private static final Logger log = Logger.getLogger( SqlTypeDescriptorRegistry.class );
private ConcurrentHashMap<Integer,SqlTypeDescriptor> descriptorMap = new ConcurrentHashMap<Integer, SqlTypeDescriptor>();
private SqlTypeDescriptorRegistry() {
addDescriptor( BooleanTypeDescriptor.INSTANCE );
addDescriptor( BitTypeDescriptor.INSTANCE );
addDescriptor( BigIntTypeDescriptor.INSTANCE );
addDescriptor( DecimalTypeDescriptor.INSTANCE );
addDescriptor( DoubleTypeDescriptor.INSTANCE );
addDescriptor( FloatTypeDescriptor.INSTANCE );
addDescriptor( IntegerTypeDescriptor.INSTANCE );
addDescriptor( NumericTypeDescriptor.INSTANCE );
addDescriptor( RealTypeDescriptor.INSTANCE );
addDescriptor( SmallIntTypeDescriptor.INSTANCE );
addDescriptor( TinyIntTypeDescriptor.INSTANCE );
addDescriptor( DateTypeDescriptor.INSTANCE );
addDescriptor( TimestampTypeDescriptor.INSTANCE );
addDescriptor( TimeTypeDescriptor.INSTANCE );
addDescriptor( BinaryTypeDescriptor.INSTANCE );
addDescriptor( VarbinaryTypeDescriptor.INSTANCE );
addDescriptor( LongVarbinaryTypeDescriptor.INSTANCE );
addDescriptor( BlobTypeDescriptor.DEFAULT );
addDescriptor( CharTypeDescriptor.INSTANCE );
addDescriptor( VarcharTypeDescriptor.INSTANCE );
addDescriptor( LongVarcharTypeDescriptor.INSTANCE );
addDescriptor( ClobTypeDescriptor.DEFAULT );
addDescriptor( NCharTypeDescriptor.INSTANCE );
addDescriptor( NVarcharTypeDescriptor.INSTANCE );
addDescriptor( LongNVarcharTypeDescriptor.INSTANCE );
addDescriptor( NClobTypeDescriptor.DEFAULT );
}
public void addDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
descriptorMap.put( sqlTypeDescriptor.getSqlType(), sqlTypeDescriptor );
}
public SqlTypeDescriptor getDescriptor(int jdbcTypeCode) {
SqlTypeDescriptor descriptor = descriptorMap.get( Integer.valueOf( jdbcTypeCode ) );
if ( descriptor != null ) {
return descriptor;
}
if ( JdbcTypeNameMapper.isStandardTypeCode( jdbcTypeCode ) ) {
log.debugf(
"A standard JDBC type code [%s] was not defined in SqlTypeDescriptorRegistry",
jdbcTypeCode
);
}
JdbcTypeFamilyInformation.Family family = JdbcTypeFamilyInformation.INSTANCE.locateJdbcTypeFamilyByTypeCode( jdbcTypeCode );
if ( family != null ) {
for ( int potentialAlternateTypeCode : family.getTypeCodes() ) {
if ( potentialAlternateTypeCode != jdbcTypeCode ) {
final SqlTypeDescriptor potentialAlternateDescriptor = descriptorMap.get( Integer.valueOf( potentialAlternateTypeCode ) );
if ( potentialAlternateDescriptor != null ) {
return potentialAlternateDescriptor;
}
if ( JdbcTypeNameMapper.isStandardTypeCode( potentialAlternateTypeCode ) ) {
log.debugf(
"A standard JDBC type code [%s] was not defined in SqlTypeDescriptorRegistry",
potentialAlternateTypeCode
);
}
}
}
}
final ObjectSqlTypeDescriptor fallBackDescriptor = new ObjectSqlTypeDescriptor( jdbcTypeCode );
addDescriptor( fallBackDescriptor );
return fallBackDescriptor;
}
public static class ObjectSqlTypeDescriptor implements SqlTypeDescriptor {
private final int jdbcTypeCode;
public ObjectSqlTypeDescriptor(int jdbcTypeCode) {
this.jdbcTypeCode = jdbcTypeCode;
}
@Override
public int getSqlType() {
return jdbcTypeCode;
}
@Override
public boolean canBeRemapped() {
return true;
}
@Override
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
}
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
st.setObject( index, value, jdbcTypeCode );
}
};
}
@Override
@SuppressWarnings("unchecked")
public ValueExtractor (JavaTypeDescriptor javaTypeDescriptor) {
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
return VarbinaryTypeDescriptor.INSTANCE.getExtractor( javaTypeDescriptor );
}
return new BasicExtractor( javaTypeDescriptor, this ) {
@Override
protected Object (ResultSet rs, String name, WrapperOptions options) throws SQLException {
return rs.getObject( name );
}
@Override
protected Object (CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return statement.getObject( index );
}
@Override
protected Object (CallableStatement statement, String name, WrapperOptions options) throws SQLException {
return statement.getObject( name );
}
};
}
}
}