DataType.java

  1. /*
  2.  *
  3.  * The DbUnit Database Testing Framework
  4.  * Copyright (C)2002-2004, DbUnit.org
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  *
  20.  */

  21. package org.dbunit.dataset.datatype;

  22. import java.sql.PreparedStatement;
  23. import java.sql.ResultSet;
  24. import java.sql.SQLException;
  25. import java.sql.Types;
  26. import org.dbunit.util.RelativeDateTimeParser;
  27. import org.slf4j.Logger;
  28. import org.slf4j.LoggerFactory;

  29. /**
  30.  * Data type that maps {@link java.sql.Types} objects to their java
  31.  * counterparts. It also provides immutable constants for the most common data
  32.  * types.
  33.  *
  34.  * @see <a href=
  35.  *      "http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping.html#table1">sun
  36.  *      JDBC object mapping</a>
  37.  *
  38.  * @author Manuel Laflamme
  39.  * @version $Revision$
  40.  */
  41. public abstract class DataType
  42. {

  43.     /**
  44.      * Logger for this class
  45.      */
  46.     private static final Logger logger =
  47.             LoggerFactory.getLogger(DataType.class);

  48.     public static final DataType UNKNOWN = new UnknownDataType();

  49.     public static final DataType CHAR = new StringDataType("CHAR", Types.CHAR);
  50.     public static final DataType VARCHAR =
  51.             new StringDataType("VARCHAR", Types.VARCHAR);
  52.     public static final DataType LONGVARCHAR =
  53.             new StringDataType("LONGVARCHAR", Types.LONGVARCHAR);
  54.     public static final DataType CLOB = new ClobDataType();

  55.     public static final DataType NUMERIC =
  56.             new NumberDataType("NUMERIC", Types.NUMERIC);
  57.     public static final DataType DECIMAL =
  58.             new NumberDataType("DECIMAL", Types.DECIMAL);

  59.     public static final DataType BOOLEAN = new BooleanDataType();
  60.     public static final DataType BIT = new BitDataType();

  61.     public static final DataType TINYINT =
  62.             new IntegerDataType("TINYINT", Types.TINYINT);
  63.     public static final DataType SMALLINT =
  64.             new IntegerDataType("SMALLINT", Types.SMALLINT);
  65.     public static final DataType INTEGER =
  66.             new IntegerDataType("INTEGER", Types.INTEGER);

  67.     // public static final DataType BIGINT = new LongDataType();
  68.     public static final DataType BIGINT = new BigIntegerDataType();
  69.     /**
  70.      * Auxiliary for the BIGINT type using a long. Is currently only needed for
  71.      * method {@link DataType#forObject(Object)}.
  72.      */
  73.     public static final DataType BIGINT_AUX_LONG = new LongDataType();

  74.     public static final DataType REAL = new FloatDataType();

  75.     public static final DataType FLOAT =
  76.             new DoubleDataType("FLOAT", Types.FLOAT);
  77.     public static final DataType DOUBLE =
  78.             new DoubleDataType("DOUBLE", Types.DOUBLE);

  79.     // To calculate consistent relative date and time.
  80.     public static final RelativeDateTimeParser RELATIVE_DATE_TIME_PARSER =
  81.             new RelativeDateTimeParser();
  82.     public static final DataType DATE = new DateDataType();
  83.     public static final DataType TIME = new TimeDataType();
  84.     public static final DataType TIMESTAMP = new TimestampDataType();

  85.     public static final DataType BINARY =
  86.             new UuidAwareBytesDataType("BINARY", Types.BINARY);
  87.     public static final DataType VARBINARY =
  88.             new UuidAwareBytesDataType("VARBINARY", Types.VARBINARY);
  89.     public static final DataType LONGVARBINARY =
  90.             new UuidAwareBytesDataType("LONGVARBINARY", Types.LONGVARBINARY);
  91.     public static final DataType BLOB = new BlobDataType();

  92.     // New JDBC 4.0 types:
  93.     // todo: ROWID = -8, NCLOB = 2011, SQLXML = 2009.

  94.     public static final DataType NCHAR = new StringDataType("NCHAR", -15);

  95.     public static final DataType NVARCHAR = new StringDataType("NVARCHAR", -9);

  96.     public static final DataType LONGNVARCHAR =
  97.             new StringDataType("LONGNVARCHAR", -16);

  98.     private static final DataType[] TYPES = {VARCHAR, CHAR, LONGVARCHAR, NCHAR,
  99.             NVARCHAR, LONGNVARCHAR, CLOB, NUMERIC, DECIMAL, BOOLEAN, BIT,
  100.             INTEGER, TINYINT, SMALLINT, BIGINT, REAL, DOUBLE, FLOAT, DATE, TIME,
  101.             TIMESTAMP, VARBINARY, BINARY, LONGVARBINARY, BLOB,
  102.             // auxiliary types at the very end
  103.             BIGINT_AUX_LONG};

  104.     /**
  105.      * Returns the specified value typecasted to this <code>DataType</code>
  106.      */
  107.     public abstract Object typeCast(Object value) throws TypeCastException;

  108.     /**
  109.      * Returns a negative integer, zero, or a positive integer as the first
  110.      * argument is less than, equal to, or greater than the second.
  111.      * <p>
  112.      * The two values are typecast to this DataType before being compared.
  113.      *
  114.      * @throws TypeCastException
  115.      *             if the arguments' types prevent them from being compared by
  116.      *             this Comparator.
  117.      */
  118.     public abstract int compare(Object o1, Object o2) throws TypeCastException;

  119.     /**
  120.      * Returns the corresponding {@link java.sql.Types}.
  121.      */
  122.     public abstract int getSqlType();

  123.     /**
  124.      * Returns the runtime class of the typecast result.
  125.      */
  126.     public abstract Class getTypeClass();

  127.     /**
  128.      * Returns the SQL type name for user types (null for basic SQL types)
  129.      */
  130.     public String getSqlTypeName()
  131.     {
  132.         return null;
  133.     }

  134.     /**
  135.      * Returns <code>true</code> if this <code>DataType</code> represents a
  136.      * number.
  137.      */
  138.     public abstract boolean isNumber();

  139.     /**
  140.      * Returns <code>true</code> if this <code>DataType</code> represents a date
  141.      * and/or time.
  142.      */
  143.     public abstract boolean isDateTime();

  144.     /**
  145.      * Returns the specified column value from the specified resultset object.
  146.      */
  147.     public abstract Object getSqlValue(int column, ResultSet resultSet)
  148.             throws SQLException, TypeCastException;

  149.     /**
  150.      * Set the specified value to the specified prepared statement object.
  151.      */
  152.     public abstract void setSqlValue(Object value, int column,
  153.             PreparedStatement statement) throws SQLException, TypeCastException;

  154.     /**
  155.      * Typecast the specified value to string.
  156.      */
  157.     public static String asString(Object value) throws TypeCastException
  158.     {
  159.         logger.debug("asString(value={}) - start", value);

  160.         return (String) DataType.VARCHAR.typeCast(value);
  161.     }

  162.     /**
  163.      * Returns the <code>DataType</code> corresponding to the specified Sql
  164.      * type. See {@link java.sql.Types}.
  165.      *
  166.      */
  167.     public static DataType forSqlType(int sqlType) throws DataTypeException
  168.     {
  169.         logger.debug("forSqlType(sqlType={}) - start", sqlType);

  170.         for (int i = 0; i < TYPES.length; i++)
  171.         {
  172.             if (sqlType == TYPES[i].getSqlType())
  173.             {
  174.                 return TYPES[i];
  175.             }
  176.         }

  177.         return UNKNOWN;
  178.     }

  179.     /**
  180.      * Returns the <code>DataType</code> corresponding to the specified Sql type
  181.      * name.
  182.      *
  183.      * @deprecated Should not be used anymore
  184.      */
  185.     public static DataType forSqlTypeName(String sqlTypeName)
  186.             throws DataTypeException
  187.     {
  188.         logger.debug("forSqlTypeName(sqlTypeName={}) - start", sqlTypeName);

  189.         for (int i = 0; i < TYPES.length; i++)
  190.         {
  191.             if (sqlTypeName.equals(TYPES[i].toString()))
  192.             {
  193.                 return TYPES[i];
  194.             }
  195.         }

  196.         return UNKNOWN;
  197.     }

  198.     /**
  199.      * Returns the <code>DataType</code> corresponding to the specified value
  200.      * runtime class. This method returns <code>DataType.UNKNOWN</code> if the
  201.      * value is <code>null</code> or runtime class not recognized.
  202.      */
  203.     public static DataType forObject(Object value)
  204.     {
  205.         logger.debug("forObject(value={}) - start", value);

  206.         if (value == null)
  207.         {
  208.             return UNKNOWN;
  209.         }

  210.         for (int i = 0; i < TYPES.length; i++)
  211.         {
  212.             Class typeClass = TYPES[i].getTypeClass();
  213.             if (typeClass.isInstance(value))
  214.             {
  215.                 return TYPES[i];
  216.             }
  217.         }

  218.         return UNKNOWN;
  219.     }

  220.     /**
  221.      * Performs a quick check to test if the specified string uses extended
  222.      * syntax.
  223.      *
  224.      * @param input
  225.      *            a string to check.
  226.      * @return {@code true} if the input uses extended syntax; {@code false}
  227.      *         otherwise.
  228.      */
  229.     protected static boolean isExtendedSyntax(String input)
  230.     {
  231.         return !input.isEmpty() && input.charAt(0) == '[';
  232.     }
  233. }