package org.simpleflatmapper.jdbc;
import org.simpleflatmapper.reflect.getter.BytesUUIDGetter;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.reflect.getter.GetterFactoryRegistry;
import org.simpleflatmapper.reflect.getter.StringUUIDGetter;
import org.simpleflatmapper.reflect.getter.UUIDUnspecifiedTypeGetter;
import org.simpleflatmapper.map.MapperBuildingException;
import org.simpleflatmapper.reflect.Getter;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.*;
import java.util.Date;
import java.util.UUID;
import org.simpleflatmapper.jdbc.impl.getter.BigDecimalResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.BigIntegerResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.BlobResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.BooleanResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.ByteArrayResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.ByteResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.CalendarResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.CharacterResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.ClobResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.DateResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.DoubleResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.FloatResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.InputStreamResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.IntResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.LongResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.NClobResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.NReaderResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.NStringResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.ObjectResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.ReaderResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.RefResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.RowIdResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.SQLXMLResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.ShortResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.SqlArrayResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.StringResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.TimeResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.TimestampResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.UndefinedDateResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.UrlFromStringResultSetGetter;
import org.simpleflatmapper.jdbc.impl.getter.UrlResultSetGetter;
import org.simpleflatmapper.util.TypeHelper;
public final class ResultSetGetterFactory implements GetterFactory<ResultSet, JdbcColumnKey> {
public static final ResultSetGetterFactory INSTANCE = new ResultSetGetterFactory();
private ResultSetGetterFactory() {
}
public static final GetterFactory<ResultSet, JdbcColumnKey> DATE_GETTER_FACTORY = new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
switch (key.getSqlType()) {
case JdbcColumnKey.UNDEFINED_TYPE:
return (Getter<ResultSet, P>) new UndefinedDateResultSetGetter(key.getIndex());
case Types.TIMESTAMP:
return (Getter<ResultSet, P>) new TimestampResultSetGetter(key.getIndex());
case Types.DATE:
return (Getter<ResultSet, P>) new DateResultSetGetter(key.getIndex());
case Types.TIME:
return (Getter<ResultSet, P>) new TimeResultSetGetter(key.getIndex());
default:
return null;
}
}
};
public static final class StringResultSetGetterFactory implements
GetterFactory<ResultSet, JdbcColumnKey> {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
switch(key.getSqlType() ) {
case Types.NCHAR:
case Types.NVARCHAR:
case Types.LONGNVARCHAR:
case Types.NCLOB:
return (Getter<ResultSet, P>) new NStringResultSetGetter(key.getIndex());
default:
return (Getter<ResultSet, P>) new StringResultSetGetter(key.getIndex());
}
}
}
private static final GetterFactoryRegistry<ResultSet, JdbcColumnKey> factoryRegistry =
new GetterFactoryRegistry<ResultSet, JdbcColumnKey>();
static {
factoryRegistry.put(String.class, new StringResultSetGetterFactory());
factoryRegistry.put(Date.class, DATE_GETTER_FACTORY);
// see http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
//IFJAVA8_START
factoryRegistry.put(java.time.OffsetTime.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
if (key.getSqlType() == Types.TIME_WITH_TIMEZONE) {
return (Getter<ResultSet, P>) new ObjectResultSetGetter(key.getIndex());
}
return null;
}
});
factoryRegistry.put(java.time.OffsetDateTime.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
if (key.getSqlType() == Types.TIMESTAMP_WITH_TIMEZONE) {
return (Getter<ResultSet, P>) new ObjectResultSetGetter(key.getIndex());
}
return null;
}
});
//IFJAVA8_END
factoryRegistry.put(java.util.Calendar.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
Getter<ResultSet, Date> dateGetter = DATE_GETTER_FACTORY.newGetter(Date.class, key, properties);
if (dateGetter != null) {
return (Getter<ResultSet, P>) new CalendarResultSetGetter(dateGetter);
}
return null;
}
});
factoryRegistry.put(java.sql.Date.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new DateResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(java.sql.Timestamp.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new TimestampResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(java.sql.Time.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new TimeResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Boolean.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new BooleanResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Byte.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new ByteResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Character.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new CharacterResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Short.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new ShortResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Integer.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new IntResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Long.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new LongResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Float.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new FloatResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Double.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new DoubleResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(BigInteger.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new BigIntegerResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(BigDecimal.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new BigDecimalResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(URL.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
if (key.getSqlType() == Types.DATALINK) {
return (Getter<ResultSet, P>) new UrlResultSetGetter(key.getIndex());
} else {
return (Getter<ResultSet, P>) new UrlFromStringResultSetGetter(key.getIndex());
}
}
});
factoryRegistry.put(byte[].class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new ByteArrayResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(InputStream.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new InputStreamResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Blob.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new BlobResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Reader.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
switch (key.getSqlType()) {
case Types.LONGNVARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
case Types.NCLOB:
return (Getter<ResultSet, P>) new NReaderResultSetGetter(key.getIndex());
default:
return (Getter<ResultSet, P>) new ReaderResultSetGetter(key.getIndex());
}
}
});
factoryRegistry.put(Clob.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new ClobResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(NClob.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new NClobResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Ref.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new RefResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(RowId.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new RowIdResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(SQLXML.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new SQLXMLResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(Array.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType, JdbcColumnKey key, Object... properties) {
return (Getter<ResultSet, P>) new SqlArrayResultSetGetter(key.getIndex());
}
});
factoryRegistry.put(UUID.class, new GetterFactory<ResultSet, JdbcColumnKey>() {
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type target, JdbcColumnKey key, Object... properties) {
switch (key.getSqlType()) {
case JdbcColumnKey.UNDEFINED_TYPE:
return (Getter<ResultSet, P>)
new UUIDUnspecifiedTypeGetter<ResultSet>(new ObjectResultSetGetter(key.getIndex()));
case Types.CHAR:
case Types.LONGVARCHAR:
case Types.VARCHAR:
case Types.CLOB:
return (Getter<ResultSet, P>) new StringUUIDGetter<ResultSet>(new StringResultSetGetter(key.getIndex()));
case Types.LONGNVARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
case Types.NCLOB:
return (Getter<ResultSet, P>) new StringUUIDGetter<ResultSet>(new NStringResultSetGetter(key.getIndex()));
case Types.BINARY:
case Types.LONGVARBINARY:
case Types.VARBINARY:
return (Getter<ResultSet, P>) new BytesUUIDGetter<ResultSet>(new ByteArrayResultSetGetter(key.getIndex()));
case Types.OTHER:
// assume it's a UUID postgres
return (Getter<ResultSet, P>) new ObjectResultSetGetter(key.getIndex());
default:
throw new MapperBuildingException("Incompatible type " + key.getSqlType() + " with UUID");
}
}
});
}
@SuppressWarnings("unchecked")
@Override
public <P> Getter<ResultSet, P> newGetter(Type genericType,
JdbcColumnKey key, Object... properties) {
Class<?> clazz = TypeHelper.wrap(TypeHelper.toClass(genericType));
if (Object.class.equals(clazz)) {
return (Getter<ResultSet, P>) new ObjectResultSetGetter(key.getIndex());
}
GetterFactory<ResultSet, JdbcColumnKey> getterFactory =
factoryRegistry.findFactoryFor(clazz);
Getter<ResultSet, P> getter = null;
if (getterFactory != null) {
getter = (Getter<ResultSet, P>) getterFactory.newGetter(genericType, key, properties);
}
if (getter == null) {
if (SQLData.class.isAssignableFrom(clazz) || key.getSqlType() == Types.JAVA_OBJECT) {
return (Getter<ResultSet, P>) new ObjectResultSetGetter(key.getIndex());
}
}
return getter;
}
}