package org.hibernate.id;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.CustomType;
import org.hibernate.type.Type;
public final class IdentifierGeneratorHelper {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( IdentifierGeneratorHelper.class );
public static final Serializable SHORT_CIRCUIT_INDICATOR = new Serializable() {
@Override
public String toString() {
return "SHORT_CIRCUIT_INDICATOR";
}
};
public static final Serializable POST_INSERT_INDICATOR = new Serializable() {
@Override
public String toString() {
return "POST_INSERT_INDICATOR";
}
};
public static Serializable getGeneratedIdentity(ResultSet rs, String identifier, Type type, Dialect dialect)
throws SQLException, HibernateException {
if ( !rs.next() ) {
throw new HibernateException( "The database returned no natively generated identity value" );
}
final Serializable id = get( rs, identifier, type, dialect );
LOG.debugf( "Natively generated identity: %s", id );
return id;
}
public static Serializable get(ResultSet rs, String identifier, Type type, Dialect dialect)
throws SQLException, IdentifierGenerationException {
if ( ResultSetIdentifierConsumer.class.isInstance( type ) ) {
return ( (ResultSetIdentifierConsumer) type ).consumeIdentifier( rs );
}
if ( CustomType.class.isInstance( type ) ) {
final CustomType customType = (CustomType) type;
if ( ResultSetIdentifierConsumer.class.isInstance( customType.getUserType() ) ) {
return ( (ResultSetIdentifierConsumer) customType.getUserType() ).consumeIdentifier( rs );
}
}
ResultSetMetaData resultSetMetaData = null;
int columnCount = 1;
try {
resultSetMetaData = rs.getMetaData();
columnCount = resultSetMetaData.getColumnCount();
}
catch (Exception e) {
}
Class clazz = type.getReturnedClass();
if ( columnCount == 1 ) {
if ( clazz == Long.class ) {
return rs.getLong( 1 );
}
else if ( clazz == Integer.class ) {
return rs.getInt( 1 );
}
else if ( clazz == Short.class ) {
return rs.getShort( 1 );
}
else if ( clazz == String.class ) {
return rs.getString( 1 );
}
else if ( clazz == BigInteger.class ) {
return rs.getBigDecimal( 1 ).setScale( 0, BigDecimal.ROUND_UNNECESSARY ).toBigInteger();
}
else if ( clazz == BigDecimal.class ) {
return rs.getBigDecimal( 1 ).setScale( 0, BigDecimal.ROUND_UNNECESSARY );
}
else {
throw new IdentifierGenerationException(
"unrecognized id type : " + type.getName() + " -> " + clazz.getName()
);
}
}
else {
try {
return extractIdentifier( rs, identifier, type, clazz );
}
catch (SQLException e) {
if ( StringHelper.isQuoted( identifier, dialect ) ) {
return extractIdentifier( rs, StringHelper.unquote( identifier, dialect ), type, clazz );
}
throw e;
}
}
}
private static Serializable (ResultSet rs, String identifier, Type type, Class clazz)
throws SQLException {
if ( clazz == Long.class ) {
return rs.getLong( identifier );
}
else if ( clazz == Integer.class ) {
return rs.getInt( identifier );
}
else if ( clazz == Short.class ) {
return rs.getShort( identifier );
}
else if ( clazz == String.class ) {
return rs.getString( identifier );
}
else if ( clazz == BigInteger.class ) {
return rs.getBigDecimal( identifier ).setScale( 0, BigDecimal.ROUND_UNNECESSARY ).toBigInteger();
}
else if ( clazz == BigDecimal.class ) {
return rs.getBigDecimal( identifier ).setScale( 0, BigDecimal.ROUND_UNNECESSARY );
}
else {
throw new IdentifierGenerationException(
"unrecognized id type : " + type.getName() + " -> " + clazz.getName()
);
}
}
@Deprecated
public static Number createNumber(long value, Class clazz) throws IdentifierGenerationException {
if ( clazz == Long.class ) {
return value;
}
else if ( clazz == Integer.class ) {
return (int) value;
}
else if ( clazz == Short.class ) {
return (short) value;
}
else {
throw new IdentifierGenerationException( "unrecognized id type : " + clazz.getName() );
}
}
public static IntegralDataTypeHolder getIntegralDataTypeHolder(Class integralType) {
if ( integralType == Long.class
|| integralType == Integer.class
|| integralType == Short.class ) {
return new BasicHolder( integralType );
}
else if ( integralType == BigInteger.class ) {
return new BigIntegerHolder();
}
else if ( integralType == BigDecimal.class ) {
return new BigDecimalHolder();
}
else {
throw new IdentifierGenerationException(
"Unknown integral data type for ids : " + integralType.getName()
);
}
}
public static long (IntegralDataTypeHolder holder) {
if ( holder.getClass() == BasicHolder.class ) {
( (BasicHolder) holder ).checkInitialized();
return ( (BasicHolder) holder ).value;
}
else if ( holder.getClass() == BigIntegerHolder.class ) {
( (BigIntegerHolder) holder ).checkInitialized();
return ( (BigIntegerHolder) holder ).value.longValue();
}
else if ( holder.getClass() == BigDecimalHolder.class ) {
( (BigDecimalHolder) holder ).checkInitialized();
return ( (BigDecimalHolder) holder ).value.longValue();
}
throw new IdentifierGenerationException( "Unknown IntegralDataTypeHolder impl [" + holder + "]" );
}
public static BigInteger (IntegralDataTypeHolder holder) {
if ( holder.getClass() == BasicHolder.class ) {
( (BasicHolder) holder ).checkInitialized();
return BigInteger.valueOf( ( (BasicHolder) holder ).value );
}
else if ( holder.getClass() == BigIntegerHolder.class ) {
( (BigIntegerHolder) holder ).checkInitialized();
return ( (BigIntegerHolder) holder ).value;
}
else if ( holder.getClass() == BigDecimalHolder.class ) {
( (BigDecimalHolder) holder ).checkInitialized();
return ( (BigDecimalHolder) holder ).value.toBigInteger();
}
throw new IdentifierGenerationException( "Unknown IntegralDataTypeHolder impl [" + holder + "]" );
}
public static BigDecimal (IntegralDataTypeHolder holder) {
if ( holder.getClass() == BasicHolder.class ) {
( (BasicHolder) holder ).checkInitialized();
return BigDecimal.valueOf( ( (BasicHolder) holder ).value );
}
else if ( holder.getClass() == BigIntegerHolder.class ) {
( (BigIntegerHolder) holder ).checkInitialized();
return new BigDecimal( ( (BigIntegerHolder) holder ).value );
}
else if ( holder.getClass() == BigDecimalHolder.class ) {
( (BigDecimalHolder) holder ).checkInitialized();
return ( (BigDecimalHolder) holder ).value;
}
throw new IdentifierGenerationException( "Unknown IntegralDataTypeHolder impl [" + holder + "]" );
}
public static class BasicHolder implements IntegralDataTypeHolder {
private final Class exactType;
private long value = Long.MIN_VALUE;
public BasicHolder(Class exactType) {
this.exactType = exactType;
if ( exactType != Long.class && exactType != Integer.class && exactType != Short.class ) {
throw new IdentifierGenerationException( "Invalid type for basic integral holder : " + exactType );
}
}
public long getActualLongValue() {
return value;
}
public IntegralDataTypeHolder initialize(long value) {
this.value = value;
return this;
}
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException {
long value = resultSet.getLong( 1 );
if ( resultSet.wasNull() ) {
value = defaultValue;
}
return initialize( value );
}
public void bind(PreparedStatement preparedStatement, int position) throws SQLException {
LOG.tracef( "binding parameter [%s] - [%s]", position, value );
preparedStatement.setLong( position, value );
}
public IntegralDataTypeHolder increment() {
checkInitialized();
value++;
return this;
}
private void checkInitialized() {
if ( value == Long.MIN_VALUE ) {
throw new IdentifierGenerationException( "integral holder was not initialized" );
}
}
public IntegralDataTypeHolder add(long addend) {
checkInitialized();
value += addend;
return this;
}
public IntegralDataTypeHolder decrement() {
checkInitialized();
value--;
return this;
}
public IntegralDataTypeHolder subtract(long subtrahend) {
checkInitialized();
value -= subtrahend;
return this;
}
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor) {
return multiplyBy( extractLong( factor ) );
}
public IntegralDataTypeHolder multiplyBy(long factor) {
checkInitialized();
value *= factor;
return this;
}
public boolean eq(IntegralDataTypeHolder other) {
return eq( extractLong( other ) );
}
public boolean eq(long value) {
checkInitialized();
return this.value == value;
}
public boolean lt(IntegralDataTypeHolder other) {
return lt( extractLong( other ) );
}
public boolean lt(long value) {
checkInitialized();
return this.value < value;
}
public boolean gt(IntegralDataTypeHolder other) {
return gt( extractLong( other ) );
}
public boolean gt(long value) {
checkInitialized();
return this.value > value;
}
public IntegralDataTypeHolder copy() {
BasicHolder copy = new BasicHolder( exactType );
copy.value = value;
return copy;
}
public Number makeValue() {
checkInitialized();
if ( exactType == Long.class ) {
return value;
}
else if ( exactType == Integer.class ) {
return (int) value;
}
else {
return (short) value;
}
}
public Number makeValueThenIncrement() {
final Number result = makeValue();
value++;
return result;
}
public Number makeValueThenAdd(long addend) {
final Number result = makeValue();
value += addend;
return result;
}
@Override
public String toString() {
return "BasicHolder[" + exactType.getName() + "[" + value + "]]";
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
BasicHolder that = (BasicHolder) o;
return value == that.value;
}
@Override
public int hashCode() {
return (int) ( value ^ ( value >>> 32 ) );
}
}
public static class BigIntegerHolder implements IntegralDataTypeHolder {
private BigInteger value;
public IntegralDataTypeHolder initialize(long value) {
this.value = BigInteger.valueOf( value );
return this;
}
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException {
final BigDecimal rsValue = resultSet.getBigDecimal( 1 );
if ( resultSet.wasNull() ) {
return initialize( defaultValue );
}
this.value = rsValue.setScale( 0, BigDecimal.ROUND_UNNECESSARY ).toBigInteger();
return this;
}
public void bind(PreparedStatement preparedStatement, int position) throws SQLException {
preparedStatement.setBigDecimal( position, new BigDecimal( value ) );
}
public IntegralDataTypeHolder increment() {
checkInitialized();
value = value.add( BigInteger.ONE );
return this;
}
private void checkInitialized() {
if ( value == null ) {
throw new IdentifierGenerationException( "integral holder was not initialized" );
}
}
public IntegralDataTypeHolder add(long increment) {
checkInitialized();
value = value.add( BigInteger.valueOf( increment ) );
return this;
}
public IntegralDataTypeHolder decrement() {
checkInitialized();
value = value.subtract( BigInteger.ONE );
return this;
}
public IntegralDataTypeHolder subtract(long subtrahend) {
checkInitialized();
value = value.subtract( BigInteger.valueOf( subtrahend ) );
return this;
}
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor) {
checkInitialized();
value = value.multiply( extractBigInteger( factor ) );
return this;
}
public IntegralDataTypeHolder multiplyBy(long factor) {
checkInitialized();
value = value.multiply( BigInteger.valueOf( factor ) );
return this;
}
public boolean eq(IntegralDataTypeHolder other) {
checkInitialized();
return value.compareTo( extractBigInteger( other ) ) == 0;
}
public boolean eq(long value) {
checkInitialized();
return this.value.compareTo( BigInteger.valueOf( value ) ) == 0;
}
public boolean lt(IntegralDataTypeHolder other) {
checkInitialized();
return value.compareTo( extractBigInteger( other ) ) < 0;
}
public boolean lt(long value) {
checkInitialized();
return this.value.compareTo( BigInteger.valueOf( value ) ) < 0;
}
public boolean gt(IntegralDataTypeHolder other) {
checkInitialized();
return value.compareTo( extractBigInteger( other ) ) > 0;
}
public boolean gt(long value) {
checkInitialized();
return this.value.compareTo( BigInteger.valueOf( value ) ) > 0;
}
public IntegralDataTypeHolder copy() {
BigIntegerHolder copy = new BigIntegerHolder();
copy.value = value;
return copy;
}
public Number makeValue() {
checkInitialized();
return value;
}
public Number makeValueThenIncrement() {
final Number result = makeValue();
value = value.add( BigInteger.ONE );
return result;
}
public Number makeValueThenAdd(long addend) {
final Number result = makeValue();
value = value.add( BigInteger.valueOf( addend ) );
return result;
}
@Override
public String toString() {
return "BigIntegerHolder[" + value + "]";
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
BigIntegerHolder that = (BigIntegerHolder) o;
return this.value == null
? that.value == null
: value.equals( that.value );
}
@Override
public int hashCode() {
return value != null ? value.hashCode() : 0;
}
}
public static class BigDecimalHolder implements IntegralDataTypeHolder {
private BigDecimal value;
public IntegralDataTypeHolder initialize(long value) {
this.value = BigDecimal.valueOf( value );
return this;
}
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException {
final BigDecimal rsValue = resultSet.getBigDecimal( 1 );
if ( resultSet.wasNull() ) {
return initialize( defaultValue );
}
this.value = rsValue.setScale( 0, BigDecimal.ROUND_UNNECESSARY );
return this;
}
public void bind(PreparedStatement preparedStatement, int position) throws SQLException {
preparedStatement.setBigDecimal( position, value );
}
public IntegralDataTypeHolder increment() {
checkInitialized();
value = value.add( BigDecimal.ONE );
return this;
}
private void checkInitialized() {
if ( value == null ) {
throw new IdentifierGenerationException( "integral holder was not initialized" );
}
}
public IntegralDataTypeHolder add(long increment) {
checkInitialized();
value = value.add( BigDecimal.valueOf( increment ) );
return this;
}
public IntegralDataTypeHolder decrement() {
checkInitialized();
value = value.subtract( BigDecimal.ONE );
return this;
}
public IntegralDataTypeHolder subtract(long subtrahend) {
checkInitialized();
value = value.subtract( BigDecimal.valueOf( subtrahend ) );
return this;
}
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor) {
checkInitialized();
value = value.multiply( extractBigDecimal( factor ) );
return this;
}
public IntegralDataTypeHolder multiplyBy(long factor) {
checkInitialized();
value = value.multiply( BigDecimal.valueOf( factor ) );
return this;
}
public boolean eq(IntegralDataTypeHolder other) {
checkInitialized();
return value.compareTo( extractBigDecimal( other ) ) == 0;
}
public boolean eq(long value) {
checkInitialized();
return this.value.compareTo( BigDecimal.valueOf( value ) ) == 0;
}
public boolean lt(IntegralDataTypeHolder other) {
checkInitialized();
return value.compareTo( extractBigDecimal( other ) ) < 0;
}
public boolean lt(long value) {
checkInitialized();
return this.value.compareTo( BigDecimal.valueOf( value ) ) < 0;
}
public boolean gt(IntegralDataTypeHolder other) {
checkInitialized();
return value.compareTo( extractBigDecimal( other ) ) > 0;
}
public boolean gt(long value) {
checkInitialized();
return this.value.compareTo( BigDecimal.valueOf( value ) ) > 0;
}
public IntegralDataTypeHolder copy() {
BigDecimalHolder copy = new BigDecimalHolder();
copy.value = value;
return copy;
}
public Number makeValue() {
checkInitialized();
return value;
}
public Number makeValueThenIncrement() {
final Number result = makeValue();
value = value.add( BigDecimal.ONE );
return result;
}
public Number makeValueThenAdd(long addend) {
final Number result = makeValue();
value = value.add( BigDecimal.valueOf( addend ) );
return result;
}
@Override
public String toString() {
return "BigDecimalHolder[" + value + "]";
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
BigDecimalHolder that = (BigDecimalHolder) o;
return this.value == null
? that.value == null
: this.value.equals( that.value );
}
@Override
public int hashCode() {
return value != null ? value.hashCode() : 0;
}
}
private IdentifierGeneratorHelper() {
}
}