View Javadoc
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  
22  package org.dbunit.dataset.datatype;
23  
24  import java.sql.PreparedStatement;
25  import java.sql.ResultSet;
26  import java.sql.SQLException;
27  import java.sql.Types;
28  import org.dbunit.util.RelativeDateTimeParser;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   * Data type that maps {@link java.sql.Types} objects to their java
34   * counterparts. It also provides immutable constants for the most common data
35   * types.
36   * 
37   * @see <a href=
38   *      "http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping.html#table1">sun
39   *      JDBC object mapping</a>
40   * 
41   * @author Manuel Laflamme
42   * @version $Revision$
43   */
44  public abstract class DataType
45  {
46  
47      /**
48       * Logger for this class
49       */
50      private static final Logger logger =
51              LoggerFactory.getLogger(DataType.class);
52  
53      public static final DataType UNKNOWN = new UnknownDataType();
54  
55      public static final DataType CHAR = new StringDataType("CHAR", Types.CHAR);
56      public static final DataType VARCHAR =
57              new StringDataType("VARCHAR", Types.VARCHAR);
58      public static final DataType LONGVARCHAR =
59              new StringDataType("LONGVARCHAR", Types.LONGVARCHAR);
60      public static final DataType CLOB = new ClobDataType();
61  
62      public static final DataType NUMERIC =
63              new NumberDataType("NUMERIC", Types.NUMERIC);
64      public static final DataType DECIMAL =
65              new NumberDataType("DECIMAL", Types.DECIMAL);
66  
67      public static final DataType BOOLEAN = new BooleanDataType();
68      public static final DataType BIT = new BitDataType();
69  
70      public static final DataType TINYINT =
71              new IntegerDataType("TINYINT", Types.TINYINT);
72      public static final DataType SMALLINT =
73              new IntegerDataType("SMALLINT", Types.SMALLINT);
74      public static final DataType INTEGER =
75              new IntegerDataType("INTEGER", Types.INTEGER);
76  
77      // public static final DataType BIGINT = new LongDataType();
78      public static final DataType BIGINT = new BigIntegerDataType();
79      /**
80       * Auxiliary for the BIGINT type using a long. Is currently only needed for
81       * method {@link DataType#forObject(Object)}.
82       */
83      public static final DataType BIGINT_AUX_LONG = new LongDataType();
84  
85      public static final DataType REAL = new FloatDataType();
86  
87      public static final DataType FLOAT =
88              new DoubleDataType("FLOAT", Types.FLOAT);
89      public static final DataType DOUBLE =
90              new DoubleDataType("DOUBLE", Types.DOUBLE);
91  
92      // To calculate consistent relative date and time.
93      public static final RelativeDateTimeParser RELATIVE_DATE_TIME_PARSER =
94              new RelativeDateTimeParser();
95      public static final DataType DATE = new DateDataType();
96      public static final DataType TIME = new TimeDataType();
97      public static final DataType TIMESTAMP = new TimestampDataType();
98  
99      public static final DataType BINARY =
100             new UuidAwareBytesDataType("BINARY", Types.BINARY);
101     public static final DataType VARBINARY =
102             new UuidAwareBytesDataType("VARBINARY", Types.VARBINARY);
103     public static final DataType LONGVARBINARY =
104             new UuidAwareBytesDataType("LONGVARBINARY", Types.LONGVARBINARY);
105     public static final DataType BLOB = new BlobDataType();
106 
107     // New JDBC 4.0 types:
108     // todo: ROWID = -8, NCLOB = 2011, SQLXML = 2009.
109 
110     public static final DataType NCHAR = new StringDataType("NCHAR", -15);
111 
112     public static final DataType NVARCHAR = new StringDataType("NVARCHAR", -9);
113 
114     public static final DataType LONGNVARCHAR =
115             new StringDataType("LONGNVARCHAR", -16);
116 
117     private static final DataType[] TYPES = {VARCHAR, CHAR, LONGVARCHAR, NCHAR,
118             NVARCHAR, LONGNVARCHAR, CLOB, NUMERIC, DECIMAL, BOOLEAN, BIT,
119             INTEGER, TINYINT, SMALLINT, BIGINT, REAL, DOUBLE, FLOAT, DATE, TIME,
120             TIMESTAMP, VARBINARY, BINARY, LONGVARBINARY, BLOB,
121             // auxiliary types at the very end
122             BIGINT_AUX_LONG};
123 
124     /**
125      * Returns the specified value typecasted to this <code>DataType</code>
126      */
127     public abstract Object typeCast(Object value) throws TypeCastException;
128 
129     /**
130      * Returns a negative integer, zero, or a positive integer as the first
131      * argument is less than, equal to, or greater than the second.
132      * <p>
133      * The two values are typecast to this DataType before being compared.
134      *
135      * @throws TypeCastException
136      *             if the arguments' types prevent them from being compared by
137      *             this Comparator.
138      */
139     public abstract int compare(Object o1, Object o2) throws TypeCastException;
140 
141     /**
142      * Returns the corresponding {@link java.sql.Types}.
143      */
144     public abstract int getSqlType();
145 
146     /**
147      * Returns the runtime class of the typecast result.
148      */
149     public abstract Class getTypeClass();
150 
151     /**
152      * Returns the SQL type name for user types (null for basic SQL types)
153      */
154     public String getSqlTypeName()
155     {
156         return null;
157     }
158 
159     /**
160      * Returns <code>true</code> if this <code>DataType</code> represents a
161      * number.
162      */
163     public abstract boolean isNumber();
164 
165     /**
166      * Returns <code>true</code> if this <code>DataType</code> represents a date
167      * and/or time.
168      */
169     public abstract boolean isDateTime();
170 
171     /**
172      * Returns the specified column value from the specified resultset object.
173      */
174     public abstract Object getSqlValue(int column, ResultSet resultSet)
175             throws SQLException, TypeCastException;
176 
177     /**
178      * Set the specified value to the specified prepared statement object.
179      */
180     public abstract void setSqlValue(Object value, int column,
181             PreparedStatement statement) throws SQLException, TypeCastException;
182 
183     /**
184      * Typecast the specified value to string.
185      */
186     public static String asString(Object value) throws TypeCastException
187     {
188         logger.debug("asString(value={}) - start", value);
189 
190         return (String) DataType.VARCHAR.typeCast(value);
191     }
192 
193     /**
194      * Returns the <code>DataType</code> corresponding to the specified Sql
195      * type. See {@link java.sql.Types}.
196      *
197      */
198     public static DataType forSqlType(int sqlType) throws DataTypeException
199     {
200         logger.debug("forSqlType(sqlType={}) - start", sqlType);
201 
202         for (int i = 0; i < TYPES.length; i++)
203         {
204             if (sqlType == TYPES[i].getSqlType())
205             {
206                 return TYPES[i];
207             }
208         }
209 
210         return UNKNOWN;
211     }
212 
213     /**
214      * Returns the <code>DataType</code> corresponding to the specified Sql type
215      * name.
216      *
217      * @deprecated Should not be used anymore
218      */
219     public static DataType forSqlTypeName(String sqlTypeName)
220             throws DataTypeException
221     {
222         logger.debug("forSqlTypeName(sqlTypeName={}) - start", sqlTypeName);
223 
224         for (int i = 0; i < TYPES.length; i++)
225         {
226             if (sqlTypeName.equals(TYPES[i].toString()))
227             {
228                 return TYPES[i];
229             }
230         }
231 
232         return UNKNOWN;
233     }
234 
235     /**
236      * Returns the <code>DataType</code> corresponding to the specified value
237      * runtime class. This method returns <code>DataType.UNKNOWN</code> if the
238      * value is <code>null</code> or runtime class not recognized.
239      */
240     public static DataType forObject(Object value)
241     {
242         logger.debug("forObject(value={}) - start", value);
243 
244         if (value == null)
245         {
246             return UNKNOWN;
247         }
248 
249         for (int i = 0; i < TYPES.length; i++)
250         {
251             Class typeClass = TYPES[i].getTypeClass();
252             if (typeClass.isInstance(value))
253             {
254                 return TYPES[i];
255             }
256         }
257 
258         return UNKNOWN;
259     }
260 
261     /**
262      * Performs a quick check to test if the specified string uses extended
263      * syntax.
264      * 
265      * @param input
266      *            a string to check.
267      * @return {@code true} if the input uses extended syntax; {@code false}
268      *         otherwise.
269      */
270     protected static boolean isExtendedSyntax(String input)
271     {
272         return !input.isEmpty() && input.charAt(0) == '[';
273     }
274 }