package jef.database.dialect.type;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;
import java.util.IdentityHashMap;
import java.util.Map;
import jef.accelerator.bean.BeanAccessor;
import jef.common.log.LogUtil;
import jef.database.Field;
import jef.database.dialect.ColumnType;
import jef.database.dialect.DatabaseDialect;
import jef.database.jdbc.result.IResultSet;
import jef.database.jsqlparser.visitor.Expression;
import jef.database.meta.ITableMetadata;
import jef.database.wrapper.populator.ColumnDescription;
import jef.tools.DateUtils;
/**
* Java对数据库的各种数据类型映射方式
*
* @author jiyi
*
*/
public final class ColumnMappings {
private ColumnMappings() {
}
public static ColumnMapping getMapping(Field field, ITableMetadata meta, String columnName, ColumnType type, boolean pk) {
BeanAccessor beanAccessor = meta.getContainerAccessor();
Class<?> fieldType = beanAccessor.getPropertyType(field.name());
ColumnMapping mType = type.getMappingType(fieldType);
mType.init(field, columnName, type, meta);
return mType;
}
public static final ResultSetAccessor RAW = new ResultRawAccessor();
public static final ResultSetAccessor STRING = new ResultStringAccessor();
public static final ResultSetAccessor INT = new ResultIntAccessor();
public static final ResultSetAccessor LONG = new ResultLongAccessor();
public static final ResultSetAccessor DOUBLE = new ResultDoubleAccessor();
public static final ResultSetAccessor CHARACTER = new ResultCharacterAccessor(null);
public static final ResultSetAccessor FLOAT = new ResultFloatAccessor();
public static final ResultSetAccessor BOOLEAN = new ResultBooleanAccessor();
public static final ResultSetAccessor CHAR_BOOLEAN = new CharBooleanAccessor();
public static final ResultSetAccessor DATE = new ResultDateAccessor();
public static final ResultSetAccessor BIGDECIMAL = new ResultBigDecimalAccessor();
public static final ResultSetAccessor SHORT = new ResultShortAccessor();
public static final ResultSetAccessor BYTE = new ResultByteAccessor();
public static final ResultSetAccessor TIME = new ResultTimeAccessor();
public static final ResultSetAccessor TIMESTAMP = new ResultTimestampAccessor();
public static final ResultSetAccessor ROWID = new ResultRowidAccessor();
public static final ResultSetAccessor BYTES = new ResultBytesAccessor();
private static final ColumnType StringType = new ColumnType.Varchar(10);
private static final ColumnType IntType = new ColumnType.Int(4);
private static final ColumnType LongType = new ColumnType.Int(12);
private static final ColumnType FloatType = new ColumnType.Double(4, 2);
private static final ColumnType DoubleType = new ColumnType.Double(10, 8);
private static final ColumnType ClobType = new ColumnType.Clob();
private static final ColumnType BlobType = new ColumnType.Blob();
private static final ColumnType DateType = new ColumnType.Date();
private static final ColumnType TimestampType = new ColumnType.TimeStamp();
/**
* Accessor of primitive int.
*/
public static final ResultSetAccessor I = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getInt(n);
}
public boolean applyFor(int type) {
return Types.INTEGER == type || Types.SMALLINT == type || Types.TINYINT == type || Types.NUMERIC == type;
}
};
/**
* Accessor of primitive long.
*/
public static final ResultSetAccessor J = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getLong(n);
}
public boolean applyFor(int type) {
return Types.INTEGER == type || Types.SMALLINT == type || Types.TINYINT == type || Types.BIGINT == type || Types.NUMERIC == type;
}
};
/**
* Accessor of primitive short.
*/
public static final ResultSetAccessor S = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getShort(n);
}
public boolean applyFor(int type) {
return Types.SMALLINT == type || Types.TINYINT == type || Types.NUMERIC == type;
}
};
/**
* Accessor of primitive float.
*/
public static final ResultSetAccessor F = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getFloat(n);
}
public boolean applyFor(int type) {
return Types.FLOAT == type || Types.DOUBLE == type || Types.DECIMAL == type || Types.NUMERIC == type;
}
};
/**
* Accessor of primitive double.
*/
public static final ResultSetAccessor D = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getDouble(n);
}
public boolean applyFor(int type) {
return Types.FLOAT == type || Types.DOUBLE == type || Types.DECIMAL == type || Types.NUMERIC == type;
}
};
/**
* Accessor of primitive boolean.
*/
public static final ResultSetAccessor Z = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getBoolean(n);
}
public boolean applyFor(int type) {
return true;// Types.INTEGER==type || Types.SMALLINT==type
// ||Types.TINYINT==type ||Types.BIGINT==type ||
// Types.BOOLEAN==type||Types.NUMERIC==type
// ||Types.BIT==type;
}
};
/**
* Accessor of primitive byte.
*/
public static final ResultSetAccessor B = new ResultSetAccessor() {
public Object jdbcGet(IResultSet rs, int n) throws SQLException {
return rs.getByte(n);
}
public boolean applyFor(int type) {
return true;
}
};
private static final Map<Class<?>, ResultSetAccessor> FAST_ACCESSOR_MAP_PRIMTIVE = new IdentityHashMap<Class<?>, ResultSetAccessor>();
private static final Map<Class<?>, ResultSetAccessor> FAST_ACCESSOR_MAP = new IdentityHashMap<Class<?>, ResultSetAccessor>();
static {
FAST_ACCESSOR_MAP_PRIMTIVE.put(Integer.TYPE, I);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Long.TYPE, J);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Float.TYPE, F);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Short.TYPE, S);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Double.TYPE, D);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Boolean.TYPE, Z);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Byte.TYPE, B);
FAST_ACCESSOR_MAP_PRIMTIVE.put(Character.TYPE, new ResultCharacterAccessor((char)0));
FAST_ACCESSOR_MAP.put(Integer.TYPE, INT);
FAST_ACCESSOR_MAP.put(Long.TYPE, LONG);
FAST_ACCESSOR_MAP.put(Float.TYPE, FLOAT);
FAST_ACCESSOR_MAP.put(Double.TYPE, DOUBLE);
FAST_ACCESSOR_MAP.put(Boolean.TYPE, BOOLEAN);
FAST_ACCESSOR_MAP.put(Short.TYPE, SHORT);
FAST_ACCESSOR_MAP.put(Byte.TYPE, BYTE);
FAST_ACCESSOR_MAP.put(Character.TYPE, CHARACTER);
FAST_ACCESSOR_MAP.put(Integer.class, INT);
FAST_ACCESSOR_MAP.put(Long.class, LONG);
FAST_ACCESSOR_MAP.put(Float.class, FLOAT);
FAST_ACCESSOR_MAP.put(Double.class, DOUBLE);
FAST_ACCESSOR_MAP.put(Boolean.class, BOOLEAN);
FAST_ACCESSOR_MAP.put(Short.class, SHORT);
FAST_ACCESSOR_MAP.put(Byte.class, BYTE);
FAST_ACCESSOR_MAP.put(Character.class, CHARACTER);
FAST_ACCESSOR_MAP.put(String.class, STRING);
FAST_ACCESSOR_MAP.put(java.util.Date.class, TIMESTAMP);
FAST_ACCESSOR_MAP.put(BigDecimal.class, BIGDECIMAL);
FAST_ACCESSOR_MAP.put(java.sql.Date.class, DATE);
FAST_ACCESSOR_MAP.put(java.sql.Time.class, TIME);
FAST_ACCESSOR_MAP.put(java.sql.Timestamp.class, TIMESTAMP);
FAST_ACCESSOR_MAP.put(byte[].class, BYTES);
FAST_ACCESSOR_MAP.put(Object.class, RAW);
}
/**
* 根据值得到ResultSetAccessor
*
* @param javaType
* @param ctype
* @param c
* @param allowPrmitive
* @return
*/
public static ResultSetAccessor getAccessor(Class<?> javaType, ColumnMapping ctype, ColumnDescription c, boolean allowPrmitive) {
/*
* 已知字段映射
*/
if (ctype != null) {
if (javaType == null || javaType == ctype.getFieldType() || javaType.isAssignableFrom(ctype.getFieldType())) {
return ctype;
}
}
ResultSetAccessor rsa;
if (allowPrmitive && javaType.isPrimitive()) {
rsa = FAST_ACCESSOR_MAP_PRIMTIVE.get(javaType);
if (rsa != null) {
return rsa;
}
} else {
rsa = FAST_ACCESSOR_MAP.get(javaType);
if (rsa != null && rsa.applyFor(c.getType())) {
return rsa;
}
}
if (c.getType() == 0) {
return RAW;
}
try {
// LogUtil.warn("Dynamic Mapping creating from [{}] to sql-type:[{}]",
// javaType.getName(), c.getType());
switch (c.getType()) {
case Types.LONGNVARCHAR:
case Types.LONGVARCHAR:
case Types.NVARCHAR:
case Types.NCHAR:
case Types.VARCHAR:
case Types.CHAR:
return StringType.getMappingType(javaType);
case Types.INTEGER:
case Types.SMALLINT:
case Types.TINYINT:
return IntType.getMappingType(javaType);
case Types.BIGINT:
return LongType.getMappingType(javaType);
case Types.REAL:
case Types.DOUBLE:
return DoubleType.getMappingType(javaType);
case Types.FLOAT:
return FloatType.getMappingType(javaType);
// case Types.NUMERIC:
// case Types.DECIMAL:
// case Types.REAL:
case Types.BINARY:
case Types.LONGVARBINARY:
case Types.BLOB:
return BlobType.getMappingType(javaType);
case Types.CLOB:
case Types.NCLOB:
return ClobType.getMappingType(javaType);
case Types.BOOLEAN:
return new BooleanBoolMapping();
case Types.DATE:
return DateType.getMappingType(javaType);
case Types.TIME:
case Types.TIMESTAMP:
return TimestampType.getMappingType(javaType);
case Types.ROWID:
return ROWID;
default:
if (rsa != null) {
LogUtil.warn("The result accessor [{}] was nor extractly match the column type[{}], but no better accessor was found.", rsa, c.getType());
return rsa;
}
throw new IllegalArgumentException("No Proper Accessor found! " + c+"expect java:"+javaType);
}
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(c.toString(), e);
}
}
/**
* 得到某个值在该数据库下的表达式
*
* @param value
* @param profile
* @return
*/
public static String getSqlStr(Object value, DatabaseDialect profile) {
if (value == null)
return "null";
if (value instanceof Expression) {
return value.toString();
} else if (value instanceof String) {
return AColumnMapping.wrapSqlStr((String) value);
} else if (value instanceof java.lang.Number) {
return value.toString();
} else if (value instanceof java.util.Date) {
Date date = (Date) value;
if (DateUtils.isDayBegin(date)) {
return profile.getSqlDateExpression(date);
} else {
return profile.getSqlTimestampExpression(date);
}
}
throw new NullPointerException("Unknown javaField Type." + value);
}
}