/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* Helper for generically dealing with literal values.
*
* @author Steve Ebersole
*/
public class ValueHandlerFactory {
private ValueHandlerFactory() {
}
public static interface ValueHandler<T> {
public T convert(Object value);
public String render(T value);
}
public static abstract class BaseValueHandler<T> implements ValueHandler<T>, Serializable {
public String render(T value) {
return value.toString();
}
}
public static class NoOpValueHandler<T> extends BaseValueHandler<T> {
@SuppressWarnings({ "unchecked" })
public T convert(Object value) {
return (T) value;
}
}
public static boolean isCharacter(Class type) {
return String.class.isAssignableFrom( type )
|| Character.class.isAssignableFrom( type )
|| Character.TYPE.equals( type );
}
public static boolean isCharacter(Object value) {
return String.class.isInstance( value )
|| Character.class.isInstance( value )
|| Character.TYPE.isInstance( value );
}
public static boolean isNumeric(Class type) {
return Number.class.isAssignableFrom( type )
|| Byte.TYPE.equals( type )
|| Short.TYPE.equals( type )
|| Integer.TYPE.equals( type )
|| Long.TYPE.equals( type )
|| Float.TYPE.equals( type )
|| Double.TYPE.equals( type );
}
public static boolean isNumeric(Object value) {
return Number.class.isInstance( value )
|| Byte.TYPE.isInstance( value )
|| Short.TYPE.isInstance( value )
|| Integer.TYPE.isInstance( value )
|| Long.TYPE.isInstance( value )
|| Float.TYPE.isInstance( value )
|| Double.TYPE.isInstance( value );
}
public static class ByteValueHandler extends BaseValueHandler<Byte> implements Serializable {
public static final ByteValueHandler INSTANCE = new ByteValueHandler();
@SuppressWarnings({ "UnnecessaryBoxing" })
public Byte convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return Byte.valueOf( ( (Number) value ).byteValue() );
}
else if ( String.class.isInstance( value ) ) {
return Byte.valueOf( ( (String) value ) );
}
throw unknownConversion( value, Byte.class );
}
}
public static class ShortValueHandler extends BaseValueHandler<Short> implements Serializable {
public static final ShortValueHandler INSTANCE = new ShortValueHandler();
@SuppressWarnings({ "UnnecessaryBoxing" })
public Short convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return Short.valueOf( ( (Number) value ).shortValue() );
}
else if ( String.class.isInstance( value ) ) {
return Short.valueOf( ( (String) value ) );
}
throw unknownConversion( value, Short.class );
}
}
public static class IntegerValueHandler extends BaseValueHandler<Integer> implements Serializable {
public static final IntegerValueHandler INSTANCE = new IntegerValueHandler();
@SuppressWarnings({ "UnnecessaryBoxing" })
public Integer convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return Integer.valueOf( ( (Number) value ).intValue() );
}
else if ( String.class.isInstance( value ) ) {
return Integer.valueOf( ( (String) value ) );
}
throw unknownConversion( value, Integer.class );
}
}
public static class LongValueHandler extends BaseValueHandler<Long> implements Serializable {
public static final LongValueHandler INSTANCE = new LongValueHandler();
@SuppressWarnings({ "UnnecessaryBoxing" })
public Long convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return Long.valueOf( ( (Number) value ).longValue() );
}
else if ( String.class.isInstance( value ) ) {
return Long.valueOf( ( (String) value ) );
}
throw unknownConversion( value, Long.class );
}
@Override
public String render(Long value) {
return value.toString() + 'L';
}
}
public static class FloatValueHandler extends BaseValueHandler<Float> implements Serializable {
public static final FloatValueHandler INSTANCE = new FloatValueHandler();
@SuppressWarnings({ "UnnecessaryBoxing" })
public Float convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return Float.valueOf( ( (Number) value ).floatValue() );
}
else if ( String.class.isInstance( value ) ) {
return Float.valueOf( ( (String) value ) );
}
throw unknownConversion( value, Float.class );
}
@Override
public String render(Float value) {
return value.toString() + 'F';
}
}
public static class DoubleValueHandler extends BaseValueHandler<Double> implements Serializable {
public static final DoubleValueHandler INSTANCE = new DoubleValueHandler();
@SuppressWarnings({ "UnnecessaryBoxing" })
public Double convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return Double.valueOf( ( (Number) value ).doubleValue() );
}
else if ( String.class.isInstance( value ) ) {
return Double.valueOf( ( (String) value ) );
}
throw unknownConversion( value, Double.class );
}
@Override
public String render(Double value) {
return value.toString() + 'D';
}
}
public static class BigIntegerValueHandler extends BaseValueHandler<BigInteger> implements Serializable {
public static final BigIntegerValueHandler INSTANCE = new BigIntegerValueHandler();
public BigInteger convert(Object value) {
if ( value == null ) {
return null;
}
if ( Number.class.isInstance( value ) ) {
return BigInteger.valueOf( ( (Number) value ).longValue() );
}
else if ( String.class.isInstance( value ) ) {
return new BigInteger( (String) value );
}
throw unknownConversion( value, BigInteger.class );
}
@Override
public String render(BigInteger value) {
return value.toString() + "BI";
}
}
public static class BigDecimalValueHandler extends BaseValueHandler<BigDecimal> implements Serializable {
public static final BigDecimalValueHandler INSTANCE = new BigDecimalValueHandler();
public BigDecimal convert(Object value) {
if ( value == null ) {
return null;
}
if ( BigInteger.class.isInstance( value ) ) {
return new BigDecimal( (BigInteger) value );
}
else if ( Number.class.isInstance( value ) ) {
return BigDecimal.valueOf( ( (Number) value ).doubleValue() );
}
else if ( String.class.isInstance( value ) ) {
return new BigDecimal( (String) value );
}
throw unknownConversion( value, BigDecimal.class );
}
@Override
public String render(BigDecimal value) {
return value.toString() + "BD";
}
}
public static class StringValueHandler extends BaseValueHandler<String> implements Serializable {
public static final StringValueHandler INSTANCE = new StringValueHandler();
public String convert(Object value) {
return value == null ? null : value.toString();
}
}
private static IllegalArgumentException unknownConversion(Object value, Class type) {
return new IllegalArgumentException(
"Unaware how to convert value [" + value + " : " + typeName( value ) + "] to requested type [" + type.getName() + "]"
);
}
private static String typeName(Object value) {
return value == null ? "???" : value.getClass().getName();
}
/**
* Convert the given value into the specified target type.
*
* @param value The value to convert
* @param targetType The type to which it should be converted
*
* @return The converted value.
*/
@SuppressWarnings({ "unchecked" })
public static <T> T convert(Object value, Class<T> targetType) {
if ( value == null ) {
return null;
}
if ( targetType.equals( value.getClass() ) ) {
return (T) value;
}
ValueHandler<T> valueHandler = determineAppropriateHandler( targetType );
if ( valueHandler == null ) {
throw unknownConversion( value, targetType );
}
return valueHandler.convert( value );
}
/**
* Determine the appropriate {@link ValueHandlerFactory.ValueHandler} strategy for converting a value
* to the given target type
*
* @param targetType The target type (to which we want to convert values).
* @param <T> parameterized type for the target type.
* @return The conversion
*/
@SuppressWarnings({ "unchecked" })
public static <T> ValueHandler<T> determineAppropriateHandler(Class<T> targetType) {
if ( String.class.equals( targetType ) ) {
return (ValueHandler<T>) StringValueHandler.INSTANCE;
}
if ( Byte.class.equals( targetType ) || Byte.TYPE.equals( targetType ) ) {
return (ValueHandler<T>) ByteValueHandler.INSTANCE;
}
if ( Short.class.equals( targetType ) || Short.TYPE.equals( targetType ) ) {
return (ValueHandler<T>) ShortValueHandler.INSTANCE;
}
if ( Integer.class.equals( targetType ) || Integer.TYPE.equals( targetType ) ) {
return (ValueHandler<T>) IntegerValueHandler.INSTANCE;
}
if ( Long.class.equals( targetType ) || Long.TYPE.equals( targetType ) ) {
return (ValueHandler<T>) LongValueHandler.INSTANCE;
}
if ( Float.class.equals( targetType ) || Float.TYPE.equals( targetType ) ) {
return (ValueHandler<T>) FloatValueHandler.INSTANCE;
}
if ( Double.class.equals( targetType ) || Double.TYPE.equals( targetType ) ) {
return (ValueHandler<T>) DoubleValueHandler.INSTANCE;
}
if ( BigInteger.class.equals( targetType ) ) {
return (ValueHandler<T>) BigIntegerValueHandler.INSTANCE;
}
if ( BigDecimal.class.equals( targetType ) ) {
return (ValueHandler<T>) BigDecimalValueHandler.INSTANCE;
}
return null;
}
}