/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean 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.
*
* Ebean 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 Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.util.codegen;
import java.math.BigInteger;
import java.sql.Types;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import com.avaje.ebean.server.plugin.PluginProperties;
import com.avaje.ebean.util.DataTypes;
import com.avaje.ebean.util.Message;
/**
* Maps Class types to JDBC datatypes.
*/
public class JdbcTypeMap {
private static final int[] charTypes = { Types.CHAR, Types.VARCHAR, Types.LONGVARCHAR, Types.CLOB };
private final HashMap classToSqltype = new HashMap();
private final HashMap classToSqltypeLogical = new HashMap();
private final HashMap sqltypeToClass = new HashMap();
/**
* The default type to map a java.util.Date to.
*/
private final int defaultUtilDateType;
/**
* The default type to map a java.util.Calender to.
*/
private final int defaultUtilCalenderType;
/**
* The default type to map a Enum to.
*/
private final int defaultEnumType;
/**
* Create the default mapping.
*/
public JdbcTypeMap() {
this(null);
}
/**
* Create the mapping for a given ServerPlugin.
*/
public JdbcTypeMap(PluginProperties properties) {
// load standard JDBC types mapping from Classes
JdbcTypeMapFactory.addTypes(classToSqltype);
//TODO: Control mapping of BigInteger to something other than Long?
// BigInteger support built in - mapping to a Long, Hmm.
classToSqltype.put(BigInteger.class, Types.BIGINT);
// add logical types (java.util.Date etc)
JdbcTypeMapFactory.addTypesLogical(classToSqltypeLogical);
// reverse of JDBC types mapping
JdbcTypeMapFactory.addReverse(sqltypeToClass);
if (properties != null){
String enumType = properties.getProperty("type.mapping.enum", "string");
defaultEnumType = getEnumMapType(enumType);
// by default map anonymous java.util.Date to java.sql.Timestamp.
String mapType = properties.getProperty("type.mapping.java.util.Date", null);
defaultUtilDateType = getTemporalMapType(mapType);
// by default map anonymous java.util.Calendar to java.sql.Timestamp.
mapType = properties.getProperty("type.mapping.java.util.Calendar", null);
defaultUtilCalenderType = getTemporalMapType(mapType);
} else {
defaultEnumType = Types.VARCHAR;
// leaving these 0 means the @Temporal annotation is required
// if they are non 0 then @Temporal is not required (uses default)
defaultUtilDateType = 0;
defaultUtilCalenderType = 0;
}
if (defaultUtilDateType != 0){
// default mapping of java.util.Date
classToSqltype.put(java.util.Date.class, defaultUtilDateType);
}
if (defaultUtilCalenderType != 0){
// default mapping of java.util.Calendar
classToSqltype.put(java.util.Calendar.class, defaultUtilCalenderType);
}
}
/**
* Determine the default type to convert Enum's to.
*/
private int getEnumMapType(String mapType) {
if (mapType == null){
return 0;
}
if (mapType.equalsIgnoreCase("string")) {
return java.sql.Types.VARCHAR;
}
if (mapType.equalsIgnoreCase("integer")) {
return java.sql.Types.INTEGER;
}
if (mapType.equalsIgnoreCase("ordinal")) {
return java.sql.Types.INTEGER;
}
String m = "Expected string or ordinal but got ["+mapType+"]";
throw new IllegalArgumentException(m);
}
/**
* Convert the mapType String to java.sql.Types DATE TIME or TIMESTAMP.
*/
private int getTemporalMapType(String mapType) {
if (mapType == null){
return 0;
}
if (mapType.equalsIgnoreCase("time")) {
return java.sql.Types.TIME;
}
if (mapType.equalsIgnoreCase("date")) {
return java.sql.Types.DATE;
}
return java.sql.Types.TIMESTAMP;
}
/**
* Return the Class mapped to the jdbc type.
* <p>
* Used to determine the propertyType for MapBeans.
* </p>
*/
public Class getReverse(int jdbcType) {
return (Class) sqltypeToClass.get(Integer.valueOf(jdbcType));
}
/**
* Return the jdbc type for a given java class.
*/
public int getDbType(Class clz) {
if (clz.isEnum()){
// this is the default type to convert an Enum to but
// could be overridden by deployment annotation
return defaultEnumType;
}
Integer type = (Integer) classToSqltype.get(clz);
if (type != null) {
return type.intValue();
}
throw new PersistenceException(Message.msg("jdbc.type.notmapped", clz.getName()));
}
/**
* Returns a Type often matching getDbType() but with the addition of
* java.util.Date, java.util.Calendar and java.math.BigInteger.
* <p>
* A BeanProperty can have both a dbType and logicalType and most of the
* time they will be equal. When they are not equal then some type
* conversion is required.
* </p>
*/
public int getLogicalType(Class clz) {
// Check for Enum first. As subclasses are not in
// the classToSqltypeLogical map.
if (clz.isEnum()){
return DataTypes.ENUM;
}
// search for 'logical only' types (such as java.util.Date)
Integer type = (Integer) classToSqltypeLogical.get(clz);
if (type == null) {
// often just the same as DB type
type = (Integer) classToSqltype.get(clz);
}
if (type != null) {
return type.intValue();
}
throw new PersistenceException(Message.msg("jdbc.type.notmapped", clz.getName()));
}
/**
* Return true if the type is one of CHAR, VARCHAR, CLOB or LONGVARCHAR.
*/
public boolean isCharacterType(int type) {
for (int i = 0; i < charTypes.length; i++) {
if (charTypes[i] == type) {
return true;
}
}
return false;
}
}
|