/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.core.types;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLXML;
import java.sql.Types;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* <p> This is a helper class used to obtain SQL type information for java types.
* The SQL type information is obtained from java.sql.Types class. The integers and
* strings returned by methods in this class are based on constants in java.sql.Types.
*/
public final class JDBCSQLTypeInfo {
public static class TypeInfo {
String name;
int maxDisplaySize;
int defaultPrecision;
String javaClassName;
int[] jdbcTypes;
public TypeInfo(int maxDisplaySize, int precision, String name,
String javaClassName, int[] jdbcTypes) {
super();
this.maxDisplaySize = maxDisplaySize;
this.defaultPrecision = precision;
this.name = name;
this.javaClassName = javaClassName;
this.jdbcTypes = jdbcTypes;
}
}
// Prevent instantiation
private JDBCSQLTypeInfo() {}
public static final Integer DEFAULT_RADIX = 10;
public static final Integer DEFAULT_SCALE = 0;
// XML column constants
public final static Integer XML_COLUMN_LENGTH = Integer.MAX_VALUE;
private static Map<String, TypeInfo> NAME_TO_TYPEINFO = new LinkedHashMap<String, TypeInfo>();
private static Map<Integer, TypeInfo> TYPE_TO_TYPEINFO = new HashMap<Integer, TypeInfo>();
private static Map<String, TypeInfo> CLASSNAME_TO_TYPEINFO = new HashMap<String, TypeInfo>();
static {
//note the order in which these are added matters. if there are multiple sql type mappings (e.g. biginteger and bigdecimal to numeric), the latter will be the primary
addType(DataTypeManager.DefaultDataTypes.BIG_INTEGER, 20, 19, DataTypeManager.DefaultDataClasses.BIG_INTEGER.getName(), Types.NUMERIC);
addType(new String[] {DataTypeManager.DefaultDataTypes.BIG_DECIMAL, "decimal"}, 22, 20, DataTypeManager.DefaultDataClasses.BIG_DECIMAL.getName(), Types.NUMERIC, Types.DECIMAL); //$NON-NLS-1$
addType(DataTypeManager.DefaultDataTypes.GEOMETRY, Integer.MAX_VALUE, Integer.MAX_VALUE, GeometryType.class.getName(), Types.BLOB, Types.LONGVARBINARY);
addType(DataTypeManager.DefaultDataTypes.BLOB, Integer.MAX_VALUE, Integer.MAX_VALUE, Blob.class.getName(), Types.BLOB, Types.LONGVARBINARY);
addType(DataTypeManager.DefaultDataTypes.BOOLEAN, 5, 1, DataTypeManager.DefaultDataClasses.BOOLEAN.getName(), Types.BIT, Types.BOOLEAN);
addType(new String[] {DataTypeManager.DefaultDataTypes.BYTE, "tinyint"}, 4, 3, DataTypeManager.DefaultDataClasses.BYTE.getName(), Types.TINYINT); //$NON-NLS-1$
addType(DataTypeManager.DefaultDataTypes.CHAR, 1, 1, DataTypeManager.DefaultDataClasses.CHAR.getName(), Types.CHAR);
addType(DataTypeManager.DefaultDataTypes.CLOB, Integer.MAX_VALUE, Integer.MAX_VALUE, Clob.class.getName(), Types.CLOB, Types.NCLOB, Types.LONGNVARCHAR, Types.LONGVARCHAR);
addType(DataTypeManager.DefaultDataTypes.DATE, 10, 10, DataTypeManager.DefaultDataClasses.DATE.getName(), Types.DATE);
addType(DataTypeManager.DefaultDataTypes.DOUBLE, 22, 20, DataTypeManager.DefaultDataClasses.DOUBLE.getName(), Types.DOUBLE, Types.FLOAT);
addType(new String[] {DataTypeManager.DefaultDataTypes.FLOAT, "real"}, 22, 20, DataTypeManager.DefaultDataClasses.FLOAT.getName(), Types.REAL); //$NON-NLS-1$
addType(DataTypeManager.DefaultDataTypes.INTEGER, 11, 10, DataTypeManager.DefaultDataClasses.INTEGER.getName(), Types.INTEGER);
addType(new String[] {DataTypeManager.DefaultDataTypes.LONG, "bigint"}, 20, 19, DataTypeManager.DefaultDataClasses.LONG.getName(), Types.BIGINT); //$NON-NLS-1$
addType(DataTypeManager.DefaultDataTypes.OBJECT, Integer.MAX_VALUE, Integer.MAX_VALUE, DataTypeManager.DefaultDataClasses.OBJECT.getName(), Types.JAVA_OBJECT);
addType(new String[] {DataTypeManager.DefaultDataTypes.SHORT, "smallint"}, 6, 5, DataTypeManager.DefaultDataClasses.SHORT.getName(), Types.SMALLINT); //$NON-NLS-1$
addType(new String[] {DataTypeManager.DefaultDataTypes.STRING, "varchar"}, DataTypeManager.MAX_STRING_LENGTH, DataTypeManager.MAX_STRING_LENGTH, DataTypeManager.DefaultDataClasses.STRING.getName(), Types.VARCHAR, Types.NVARCHAR, Types.CHAR, Types.NCHAR); //$NON-NLS-1$
addType(DataTypeManager.DefaultDataTypes.TIME, 8, 8, DataTypeManager.DefaultDataClasses.TIME.getName(), Types.TIME);
addType(DataTypeManager.DefaultDataTypes.TIMESTAMP, 29, 29, DataTypeManager.DefaultDataClasses.TIMESTAMP.getName(), Types.TIMESTAMP);
addType(DataTypeManager.DefaultDataTypes.XML, Integer.MAX_VALUE, Integer.MAX_VALUE, SQLXML.class.getName(), Types.SQLXML);
addType(DataTypeManager.DefaultDataTypes.NULL, 4, 1, null, Types.NULL);
addType(DataTypeManager.DefaultDataTypes.VARBINARY, DataTypeManager.MAX_VARBINARY_BYTES, DataTypeManager.MAX_VARBINARY_BYTES, byte[].class.getName(), Types.VARBINARY, Types.BINARY);
TypeInfo typeInfo = new TypeInfo(Integer.MAX_VALUE, 0, "ARRAY", Array.class.getName(), new int[Types.ARRAY]); //$NON-NLS-1$
CLASSNAME_TO_TYPEINFO.put(Array.class.getName(), typeInfo);
TYPE_TO_TYPEINFO.put(Types.ARRAY, typeInfo);
}
private static TypeInfo addType(String typeName, int maxDisplaySize, int precision, String javaClassName, int... sqlTypes) {
TypeInfo ti = new TypeInfo(maxDisplaySize, precision, typeName, javaClassName, sqlTypes);
NAME_TO_TYPEINFO.put(typeName, ti);
if (javaClassName != null) {
CLASSNAME_TO_TYPEINFO.put(javaClassName, ti);
}
for (int i : sqlTypes) {
TYPE_TO_TYPEINFO.put(i, ti);
}
return ti;
}
private static void addType(String[] typeNames, int maxDisplaySize, int precision, String javaClassName, int... sqlTypes) {
TypeInfo ti = addType(typeNames[0], maxDisplaySize, precision, javaClassName, sqlTypes);
for (int i = 1; i < typeNames.length; i++) {
NAME_TO_TYPEINFO.put(typeNames[i], ti);
}
}
/**
* This method is used to obtain a short indicating JDBC SQL type for any object.
* The short values that give the type info are from java.sql.Types.
* @param Name of the teiid type.
* @return A short value representing SQL Type for the given java type.
*/
public static final int getSQLType(String typeName) {
if (typeName == null) {
return Types.NULL;
}
TypeInfo sqlType = NAME_TO_TYPEINFO.get(typeName);
if (sqlType == null) {
if (DataTypeManager.isArrayType(typeName)) {
return Types.ARRAY;
}
return Types.JAVA_OBJECT;
}
return sqlType.jdbcTypes[0];
}
/**
* Get sql Type from java class type name. This should not be called with runtime types
* as Clob and Blob are represented by ClobType and BlobType respectively.
* @param typeName
* @return int
*/
public static final int getSQLTypeFromClass(String className) {
if (className == null) {
return Types.NULL;
}
TypeInfo sqlType = CLASSNAME_TO_TYPEINFO.get(className);
if (sqlType == null) {
return Types.JAVA_OBJECT;
}
return sqlType.jdbcTypes[0];
}
/**
* Get the sql type from the given runtime type
* @param type
* @return
*/
public static final int getSQLTypeFromRuntimeType(Class<?> type) {
if (type == null) {
return Types.NULL;
}
String name = DataTypeManager.getDataTypeName(type);
if (name == null) {
return Types.JAVA_OBJECT;
}
return getSQLType(name);
}
/**
* This method is used to obtain a the java class name given an int value
* indicating JDBC SQL type. The int values that give the type info are from
* java.sql.Types.
* @param int value giving the SQL type code.
* @return A String representing the java class name for the given SQL Type.
*/
public static final String getJavaClassName(int jdbcSQLType) {
TypeInfo typeInfo = TYPE_TO_TYPEINFO.get(jdbcSQLType);
if (typeInfo == null) {
return DataTypeManager.DefaultDataClasses.OBJECT.getName();
}
return typeInfo.javaClassName;
}
public static final String getTypeName(int sqlType) {
TypeInfo typeInfo = TYPE_TO_TYPEINFO.get(sqlType);
if (typeInfo == null) {
return DataTypeManager.DefaultDataTypes.OBJECT;
}
return typeInfo.name;
}
public static Set<String> getMMTypeNames() {
return NAME_TO_TYPEINFO.keySet();
}
public static Integer getMaxDisplaySize(Class<?> dataTypeClass) {
return getMaxDisplaySize(DataTypeManager.getDataTypeName(dataTypeClass));
}
public static Integer getMaxDisplaySize(String typeName) {
TypeInfo ti = NAME_TO_TYPEINFO.get(typeName);
if (ti == null) {
return null;
}
return ti.maxDisplaySize;
}
public static Integer getDefaultPrecision(Class<?> dataTypeClass) {
return getDefaultPrecision(DataTypeManager.getDataTypeName(dataTypeClass));
}
public static Integer getDefaultPrecision(String typeName) {
TypeInfo ti = NAME_TO_TYPEINFO.get(typeName);
if (ti == null) {
return null;
}
return ti.defaultPrecision;
}
}