AbstractDataType.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.Connection;
  23. import java.sql.PreparedStatement;
  24. import java.sql.ResultSet;
  25. import java.sql.SQLException;

  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;

  28. /**
  29.  * Abstract data type implementation that provides generic methods that are
  30.  * appropriate for most data type implementations. Among those is the generic
  31.  * implementation of the {@link #compare(Object, Object)} method.
  32.  *
  33.  * @author Manuel Laflamme
  34.  * @author Last changed by: $Author$
  35.  * @version $Revision$ $Date$
  36.  * @since Mar 19, 2002
  37.  */
  38. public abstract class AbstractDataType extends DataType
  39. {

  40.     /**
  41.      * Logger for this class
  42.      */
  43.     private static final Logger logger =
  44.             LoggerFactory.getLogger(AbstractDataType.class);

  45.     private final String _name;
  46.     private final int _sqlType;
  47.     private final Class _classType;
  48.     private final boolean _isNumber;

  49.     public AbstractDataType(final String name, final int sqlType,
  50.             final Class classType, final boolean isNumber)
  51.     {
  52.         _sqlType = sqlType;
  53.         _name = name;
  54.         _classType = classType;
  55.         _isNumber = isNumber;
  56.     }

  57.     ////////////////////////////////////////////////////////////////////////////
  58.     // DataType class

  59.     @Override
  60.     public int compare(final Object o1, final Object o2)
  61.             throws TypeCastException
  62.     {
  63.         logger.debug("compare(o1={}, o2={}) - start", o1, o2);

  64.         try
  65.         {
  66.             // New in 2.3: Object level check for equality - should give massive
  67.             // performance improvements
  68.             // in the most cases because the typecast can be avoided (null
  69.             // values and equal objects)
  70.             if (areObjectsEqual(o1, o2))
  71.             {
  72.                 return 0;
  73.             }

  74.             // Comparable check based on the results of method "typeCast"
  75.             final Object value1 = typeCast(o1);
  76.             final Object value2 = typeCast(o2);

  77.             // Check for "null"s again because typeCast can produce them

  78.             if (value1 == null && value2 == null)
  79.             {
  80.                 return 0;
  81.             }

  82.             if (value1 == null && value2 != null)
  83.             {
  84.                 return -1;
  85.             }

  86.             if (value1 != null && value2 == null)
  87.             {
  88.                 return 1;
  89.             }

  90.             return compareNonNulls(value1, value2);

  91.         } catch (final ClassCastException e)
  92.         {
  93.             throw new TypeCastException(e);
  94.         }
  95.     }

  96.     /**
  97.      * Compares non-null values to each other. Both objects are guaranteed to be
  98.      * not null and to implement the interface {@link Comparable}. The two given
  99.      * objects are the results of the {@link #typeCast(Object)} method call
  100.      * which is usually implemented by a specialized {@link DataType}
  101.      * implementation.
  102.      *
  103.      * @param value1
  104.      *            First value resulting from the {@link #typeCast(Object)}
  105.      *            method call
  106.      * @param value2
  107.      *            Second value resulting from the {@link #typeCast(Object)}
  108.      *            method call
  109.      * @return The result of the {@link Comparable#compareTo(Object)}
  110.      *         invocation.
  111.      * @throws TypeCastException
  112.      */
  113.     protected int compareNonNulls(final Object value1, final Object value2)
  114.             throws TypeCastException
  115.     {
  116.         logger.debug("compareNonNulls(value1={}, value2={}) - start", value1,
  117.                 value2);

  118.         final Comparable value1comp = (Comparable) value1;
  119.         final Comparable value2comp = (Comparable) value2;
  120.         return value1comp.compareTo(value2comp);
  121.     }

  122.     /**
  123.      * Checks whether the given objects are equal or not.
  124.      *
  125.      * @param o1
  126.      *            first object
  127.      * @param o2
  128.      *            second object
  129.      * @return <code>true</code> if both objects are <code>null</code> (and
  130.      *         hence equal) or if the <code>o1.equals(o2)</code> is
  131.      *         <code>true</code>.
  132.      */
  133.     protected final boolean areObjectsEqual(final Object o1, final Object o2)
  134.     {
  135.         if (o1 == null && o2 == null)
  136.         {
  137.             return true;
  138.         }
  139.         return o1 != null && o1.equals(o2);
  140.         // Note that no more check is needed for o2 because it definitely does
  141.         // is not equal to o1
  142.         // Instead immediately proceed with the typeCast method
  143.     }

  144.     @Override
  145.     public int getSqlType()
  146.     {
  147.         logger.debug("getSqlType() - start");

  148.         return _sqlType;
  149.     }

  150.     @Override
  151.     public Class getTypeClass()
  152.     {
  153.         logger.debug("getTypeClass() - start");

  154.         return _classType;
  155.     }

  156.     @Override
  157.     public boolean isNumber()
  158.     {
  159.         logger.debug("isNumber() - start");

  160.         return _isNumber;
  161.     }

  162.     @Override
  163.     public boolean isDateTime()
  164.     {
  165.         logger.debug("isDateTime() - start");

  166.         return false;
  167.     }

  168.     @Override
  169.     public Object getSqlValue(final int column, final ResultSet resultSet)
  170.             throws SQLException, TypeCastException
  171.     {
  172.         logger.debug("getSqlValue(column={}, resultSet={}) - start", column,
  173.                 resultSet);
  174.         final Object rawValue = resultSet.getObject(column);
  175.         final Object value = resultSet.wasNull() ? null : rawValue;
  176.         logger.debug("getSqlValue: column={}, value={}", column, value);
  177.         return value;
  178.     }

  179.     @Override
  180.     public void setSqlValue(final Object value, final int column,
  181.             final PreparedStatement statement)
  182.             throws SQLException, TypeCastException
  183.     {
  184.         logger.debug("setSqlValue(value={}, column={}, statement={}) - start",
  185.                 value, column, statement);

  186.         statement.setObject(column, typeCast(value), getSqlType());
  187.     }

  188.     /**
  189.      * @param clazz
  190.      *            The fully qualified name of the class to be loaded
  191.      * @param connection
  192.      *            The JDBC connection needed to load the given class
  193.      * @return The loaded class
  194.      * @throws ClassNotFoundException
  195.      */
  196.     protected final Class loadClass(final String clazz,
  197.             final Connection connection) throws ClassNotFoundException
  198.     {
  199.         final ClassLoader connectionClassLoader =
  200.                 connection.getClass().getClassLoader();
  201.         return this.loadClass(clazz, connectionClassLoader);
  202.     }

  203.     /**
  204.      * @param clazz
  205.      *            The fully qualified name of the class to be loaded
  206.      * @param classLoader
  207.      *            The classLoader to be used to load the given class
  208.      * @return The loaded class
  209.      * @throws ClassNotFoundException
  210.      */
  211.     protected final Class loadClass(final String clazz,
  212.             final ClassLoader classLoader) throws ClassNotFoundException
  213.     {
  214.         return classLoader.loadClass(clazz);
  215.     }

  216.     ////////////////////////////////////////////////////////////////////////////
  217.     // Object class

  218.     @Override
  219.     public String toString()
  220.     {
  221.         return _name;
  222.     }
  223. }