DbUnitAssertBase.java

  1. package org.dbunit.assertion;

  2. import java.util.Arrays;
  3. import java.util.Map;

  4. import org.dbunit.DatabaseUnitException;
  5. import org.dbunit.assertion.DbUnitAssert.ComparisonColumn;
  6. import org.dbunit.assertion.comparer.value.DefaultValueComparerDefaults;
  7. import org.dbunit.assertion.comparer.value.ValueComparer;
  8. import org.dbunit.assertion.comparer.value.ValueComparerDefaults;
  9. import org.dbunit.dataset.Column;
  10. import org.dbunit.dataset.Columns;
  11. import org.dbunit.dataset.DataSetException;
  12. import org.dbunit.dataset.IDataSet;
  13. import org.dbunit.dataset.ITable;
  14. import org.dbunit.dataset.ITableMetaData;
  15. import org.dbunit.dataset.datatype.DataType;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;

  18. /**
  19.  * Base class for DbUnit assert classes containing common methods.
  20.  *
  21.  * @author Jeff Jensen
  22.  * @since 2.6.0
  23.  */
  24. public class DbUnitAssertBase
  25. {
  26.     private final Logger log = LoggerFactory.getLogger(DbUnitAssertBase.class);

  27.     private FailureFactory junitFailureFactory = getJUnitFailureFactory();

  28.     protected ValueComparerDefaults valueComparerDefaults =
  29.             new DefaultValueComparerDefaults();

  30.     /**
  31.      * @return The default failure handler
  32.      * @since 2.4
  33.      */
  34.     protected FailureHandler getDefaultFailureHandler()
  35.     {
  36.         return getDefaultFailureHandler(null);
  37.     }

  38.     /**
  39.      * @return The default failure handler
  40.      * @since 2.4
  41.      */
  42.     protected FailureHandler getDefaultFailureHandler(
  43.             final Column[] additionalColumnInfo)
  44.     {
  45.         final DefaultFailureHandler failureHandler =
  46.                 new DefaultFailureHandler(additionalColumnInfo);
  47.         if (junitFailureFactory != null)
  48.         {
  49.             failureHandler.setFailureFactory(junitFailureFactory);
  50.         }
  51.         return failureHandler;
  52.     }

  53.     /**
  54.      * @return the JUnitFailureFactory if JUnit is on the classpath or
  55.      *         <code>null</code> if JUnit is not on the classpath.
  56.      */
  57.     private FailureFactory getJUnitFailureFactory()
  58.     {
  59.         try
  60.         {
  61.             Class.forName("junit.framework.Assert");
  62.             // JUnit available
  63.             return new JUnitFailureFactory();
  64.         } catch (final ClassNotFoundException e)
  65.         {
  66.             // JUnit not available on the classpath return null
  67.             log.debug("JUnit does not seem to be on the classpath. " + e);
  68.         }
  69.         return null;
  70.     }

  71.     /**
  72.      * @param expectedTableName
  73.      * @param expectedColumns
  74.      * @param actualColumns
  75.      * @param failureHandler
  76.      *            The {@link FailureHandler} to be used when no datatype can be
  77.      *            determined
  78.      * @return The columns to be used for the assertion, including the correct
  79.      *         datatype
  80.      * @since 2.4
  81.      */
  82.     protected ComparisonColumn[] getComparisonColumns(
  83.             final String expectedTableName, final Column[] expectedColumns,
  84.             final Column[] actualColumns, final FailureHandler failureHandler)
  85.     {
  86.         final ComparisonColumn[] result =
  87.                 new ComparisonColumn[expectedColumns.length];

  88.         for (int j = 0; j < expectedColumns.length; j++)
  89.         {
  90.             final Column expectedColumn = expectedColumns[j];
  91.             final Column actualColumn = actualColumns[j];
  92.             result[j] = new ComparisonColumn(expectedTableName, expectedColumn,
  93.                     actualColumn, failureHandler);
  94.         }
  95.         return result;
  96.     }

  97.     /**
  98.      * Method to last-minute intercept the comparison of a single expected and
  99.      * actual value. Designed to be overridden in order to skip cell comparison
  100.      * by specific cell values.
  101.      *
  102.      * @param columnName
  103.      *            The column being compared
  104.      * @param expectedValue
  105.      *            The expected value to be compared
  106.      * @param actualValue
  107.      *            The actual value to be compared
  108.      * @return <code>false</code> always so that the comparison is never skipped
  109.      * @since 2.4
  110.      */
  111.     protected boolean skipCompare(final String columnName,
  112.             final Object expectedValue, final Object actualValue)
  113.     {
  114.         return false;
  115.     }

  116.     protected FailureHandler determineFailureHandler(
  117.             final FailureHandler failureHandler)
  118.     {
  119.         final FailureHandler validFailureHandler;

  120.         if (failureHandler == null)
  121.         {
  122.             log.debug("FailureHandler is null. Using default implementation");
  123.             validFailureHandler = getDefaultFailureHandler();
  124.         } else
  125.         {
  126.             validFailureHandler = failureHandler;
  127.         }

  128.         return validFailureHandler;
  129.     }

  130.     protected boolean compareRowCounts(final ITable expectedTable,
  131.             final ITable actualTable, final FailureHandler failureHandler,
  132.             final String expectedTableName) throws Error
  133.     {
  134.         boolean isTablesEmpty;

  135.         final int expectedRowsCount = expectedTable.getRowCount();
  136.         int actualRowsCount = 0;
  137.         boolean skipRowComparison = false;
  138.         try
  139.         {
  140.             actualRowsCount = actualTable.getRowCount();
  141.         } catch (final UnsupportedOperationException exception)
  142.         {
  143.             skipRowComparison = true;
  144.         }

  145.         if (skipRowComparison)
  146.         {
  147.             isTablesEmpty = false;
  148.         } else
  149.         {
  150.             if (expectedRowsCount != actualRowsCount)
  151.             {
  152.                 final String msg =
  153.                         "row count (table=" + expectedTableName + ")";
  154.                 final Error error = failureHandler.createFailure(msg,
  155.                         String.valueOf(expectedRowsCount),
  156.                         String.valueOf(actualRowsCount));
  157.                 log.error(error.toString());
  158.                 throw error;
  159.             }

  160.             // if both tables are empty, it is not necessary to compare columns,
  161.             // as such comparison can fail if column metadata is different
  162.             // (which could occurs when comparing empty tables)
  163.             if (expectedRowsCount == 0 && actualRowsCount == 0)
  164.             {
  165.                 log.debug("Tables are empty, hence equals.");
  166.                 isTablesEmpty = true;
  167.             } else
  168.             {
  169.                 isTablesEmpty = false;
  170.             }
  171.         }

  172.         return isTablesEmpty;
  173.     }

  174.     protected void compareColumns(final Column[] expectedColumns,
  175.             final Column[] actualColumns, final ITableMetaData expectedMetaData,
  176.             final ITableMetaData actualMetaData,
  177.             final FailureHandler failureHandler) throws DataSetException, Error
  178.     {
  179.         final Columns.ColumnDiff columnDiff =
  180.                 Columns.getColumnDiff(expectedMetaData, actualMetaData);
  181.         if (columnDiff.hasDifference())
  182.         {
  183.             final String message = columnDiff.getMessage();
  184.             final Error error = failureHandler.createFailure(message,
  185.                     Columns.getColumnNamesAsString(expectedColumns),
  186.                     Columns.getColumnNamesAsString(actualColumns));
  187.             log.error(error.toString());
  188.             throw error;
  189.         }
  190.     }

  191.     protected void compareTableCounts(final String[] expectedNames,
  192.             final String[] actualNames, final FailureHandler failureHandler)
  193.             throws Error
  194.     {
  195.         if (expectedNames.length != actualNames.length)
  196.         {
  197.             throw failureHandler.createFailure("table count",
  198.                     String.valueOf(expectedNames.length),
  199.                     String.valueOf(actualNames.length));
  200.         }
  201.     }

  202.     protected void compareTableNames(final String[] expectedNames,
  203.             final String[] actualNames, final FailureHandler failureHandler)
  204.             throws Error
  205.     {
  206.         for (int i = 0; i < expectedNames.length; i++)
  207.         {
  208.             if (!actualNames[i].equals(expectedNames[i]))
  209.             {
  210.                 throw failureHandler.createFailure("tables",
  211.                         Arrays.asList(expectedNames).toString(),
  212.                         Arrays.asList(actualNames).toString());
  213.             }
  214.         }
  215.     }

  216.     protected String[] getSortedTableNames(final IDataSet dataSet)
  217.             throws DataSetException
  218.     {
  219.         log.debug("getSortedTableNames(dataSet={}) - start", dataSet);

  220.         final String[] names = dataSet.getTableNames();
  221.         if (!dataSet.isCaseSensitiveTableNames())
  222.         {
  223.             for (int i = 0; i < names.length; i++)
  224.             {
  225.                 names[i] = names[i].toUpperCase();
  226.             }
  227.         }
  228.         Arrays.sort(names);
  229.         return names;
  230.     }

  231.     /**
  232.      * Asserts the two specified {@link IDataSet}s comparing their columns using
  233.      * the specified columnValueComparers or defaultValueComparer and handles
  234.      * failures using the specified failureHandler. This method ignores the
  235.      * table names, the columns order, the columns data type, and which columns
  236.      * are composing the primary keys.
  237.      *
  238.      * @param expectedDataSet
  239.      *            {@link IDataSet} containing all expected results.
  240.      * @param actualDataSet
  241.      *            {@link IDataSet} containing all actual results.
  242.      * @param failureHandler
  243.      *            The failure handler used if the assert fails because of a data
  244.      *            mismatch. Provides some additional information that may be
  245.      *            useful to quickly identify the rows for which the mismatch
  246.      *            occurred (for example by printing an additional primary key
  247.      *            column). Can be <code>null</code>.
  248.      * @param defaultValueComparer
  249.      *            {@link ValueComparer} to use with column value comparisons
  250.      *            when the column name for the table is not in the
  251.      *            tableColumnValueComparers {@link Map}. Can be
  252.      *            <code>null</code> and will default to
  253.      *            {@link #getDefaultValueComparer()}.
  254.      * @param tableColumnValueComparers
  255.      *            {@link Map} of {@link ValueComparer}s to use for specific
  256.      *            tables and columns. Key is table name, value is {@link Map} of
  257.      *            column name in the table to {@link ValueComparer}s. Can be
  258.      *            <code>null</code> and will default to using
  259.      *            {@link #getDefaultColumnValueComparerMapForTable(String)} or,
  260.      *            if that is empty, defaultValueComparer for all columns in all
  261.      *            tables.
  262.      * @throws DatabaseUnitException
  263.      */
  264.     public void assertWithValueComparer(final IDataSet expectedDataSet,
  265.             final IDataSet actualDataSet, final FailureHandler failureHandler,
  266.             final ValueComparer defaultValueComparer,
  267.             final Map<String, Map<String, ValueComparer>> tableColumnValueComparers)
  268.             throws DatabaseUnitException
  269.     {
  270.         log.debug(
  271.                 "assertWithValueComparer(expectedDataSet={}, actualDataSet={},"
  272.                         + " failureHandler={}, defaultValueComparer={},"
  273.                         + " tableColumnValueComparers={}) - start",
  274.                 expectedDataSet, actualDataSet, failureHandler,
  275.                 defaultValueComparer, tableColumnValueComparers);

  276.         // do not continue if same instance
  277.         if (expectedDataSet == actualDataSet)
  278.         {
  279.             log.debug("The given datasets reference the same object."
  280.                     + " Skipping comparisons.");
  281.             return;
  282.         }

  283.         final FailureHandler validFailureHandler =
  284.                 determineFailureHandler(failureHandler);

  285.         final String[] expectedNames = getSortedTableNames(expectedDataSet);
  286.         final String[] actualNames = getSortedTableNames(actualDataSet);

  287.         compareTableCounts(expectedNames, actualNames, validFailureHandler);

  288.         // table names in no specific order
  289.         compareTableNames(expectedNames, actualNames, validFailureHandler);

  290.         compareTables(expectedDataSet, actualDataSet, expectedNames,
  291.                 validFailureHandler, defaultValueComparer,
  292.                 tableColumnValueComparers);
  293.     }

  294.     protected void compareTables(final IDataSet expectedDataSet,
  295.             final IDataSet actualDataSet, final String[] expectedNames,
  296.             final FailureHandler failureHandler,
  297.             final ValueComparer defaultValueComparer,
  298.             final Map<String, Map<String, ValueComparer>> tableColumnValueComparers)
  299.             throws DatabaseUnitException
  300.     {
  301.         final Map<String, Map<String, ValueComparer>> validTableColumnValueComparers =
  302.                 determineValidTableColumnValueComparers(
  303.                         tableColumnValueComparers);

  304.         for (int i = 0; i < expectedNames.length; i++)
  305.         {
  306.             final String tableName = expectedNames[i];

  307.             final ITable expectedTable = expectedDataSet.getTable(tableName);
  308.             final ITable actualTable = actualDataSet.getTable(tableName);
  309.             final Map<String, ValueComparer> columnValueComparers =
  310.                     validTableColumnValueComparers.get(tableName);

  311.             assertWithValueComparer(expectedTable, actualTable, failureHandler,
  312.                     defaultValueComparer, columnValueComparers);
  313.         }
  314.     }

  315.     /**
  316.      * Asserts the two specified {@link ITable}s comparing their columns using
  317.      * the specified columnValueComparers or defaultValueComparer and handles
  318.      * failures using the specified failureHandler. This method ignores the
  319.      * table names, the columns order, the columns data type, and which columns
  320.      * are composing the primary keys.
  321.      *
  322.      * @param expectedTable
  323.      *            {@link ITable} containing all expected results.
  324.      * @param actualTable
  325.      *            {@link ITable} containing all actual results.
  326.      * @param failureHandler
  327.      *            The failure handler used if the assert fails because of a data
  328.      *            mismatch. Provides some additional information that may be
  329.      *            useful to quickly identify the rows for which the mismatch
  330.      *            occurred (for example by printing an additional primary key
  331.      *            column). Can be <code>null</code>.
  332.      * @param defaultValueComparer
  333.      *            {@link ValueComparer} to use with column value comparisons
  334.      *            when the column name for the table is not in the
  335.      *            columnValueComparers {@link Map}. Can be <code>null</code> and
  336.      *            will default to {@link #getDefaultValueComparer()}.
  337.      * @param columnValueComparers
  338.      *            {@link Map} of {@link ValueComparer}s to use for specific
  339.      *            columns. Key is column name in the table, value is
  340.      *            {@link ValueComparer} to use in comparing expected to actual
  341.      *            column values. Can be <code>null</code> and will default to
  342.      *            using
  343.      *            {@link #getDefaultColumnValueComparerMapForTable(String)} or,
  344.      *            if that is empty, defaultValueComparer for all columns in the
  345.      *            table.
  346.      * @throws DatabaseUnitException
  347.      */
  348.     public void assertWithValueComparer(final ITable expectedTable,
  349.             final ITable actualTable, final FailureHandler failureHandler,
  350.             final ValueComparer defaultValueComparer,
  351.             final Map<String, ValueComparer> columnValueComparers)
  352.             throws DatabaseUnitException
  353.     {
  354.         log.trace("assertWithValueComparer(expectedTable, actualTable,"
  355.                 + " failureHandler, defaultValueComparer,"
  356.                 + " columnValueComparers) - start");
  357.         log.debug("assertWithValueComparer: expectedTable={}", expectedTable);
  358.         log.debug("assertWithValueComparer: actualTable={}", actualTable);
  359.         log.debug("assertWithValueComparer: failureHandler={}", failureHandler);
  360.         log.debug("assertWithValueComparer: defaultValueComparer={}",
  361.                 defaultValueComparer);
  362.         log.debug("assertWithValueComparer: columnValueComparers={}",
  363.                 columnValueComparers);

  364.         // Do not continue if same instance
  365.         if (expectedTable == actualTable)
  366.         {
  367.             log.debug("The given tables reference the same object."
  368.                     + " Skipping comparisons.");
  369.             return;
  370.         }

  371.         final FailureHandler validFailureHandler =
  372.                 determineFailureHandler(failureHandler);

  373.         final ITableMetaData expectedMetaData =
  374.                 expectedTable.getTableMetaData();
  375.         final ITableMetaData actualMetaData = actualTable.getTableMetaData();
  376.         final String expectedTableName = expectedMetaData.getTableName();

  377.         final boolean isTablesEmpty = compareRowCounts(expectedTable,
  378.                 actualTable, validFailureHandler, expectedTableName);
  379.         if (isTablesEmpty)
  380.         {
  381.             return;
  382.         }

  383.         // Put the columns into the same order
  384.         final Column[] expectedColumns =
  385.                 Columns.getSortedColumns(expectedMetaData);
  386.         final Column[] actualColumns = Columns.getSortedColumns(actualMetaData);

  387.         // Verify columns
  388.         compareColumns(expectedColumns, actualColumns, expectedMetaData,
  389.                 actualMetaData, validFailureHandler);

  390.         // Get the datatypes to be used for comparing the sorted columns
  391.         final ComparisonColumn[] comparisonCols =
  392.                 getComparisonColumns(expectedTableName, expectedColumns,
  393.                         actualColumns, validFailureHandler);

  394.         // Finally compare the data
  395.         compareData(expectedTable, actualTable, comparisonCols,
  396.                 validFailureHandler, defaultValueComparer,
  397.                 columnValueComparers);
  398.     }

  399.     /**
  400.      * @param expectedTable
  401.      *            Table containing all expected results.
  402.      * @param actualTable
  403.      *            Table containing all actual results.
  404.      * @param comparisonCols
  405.      *            The columns to be compared, also including the correct
  406.      *            {@link DataType}s for comparison
  407.      * @param failureHandler
  408.      *            The failure handler used if the assert fails because of a data
  409.      *            mismatch. Provides some additional information that may be
  410.      *            useful to quickly identify the rows for which the mismatch
  411.      *            occurred (for example by printing an additional primary key
  412.      *            column). Must not be <code>null</code> at this stage
  413.      * @throws DataSetException
  414.      * @since 2.4
  415.      */
  416.     protected void compareData(final ITable expectedTable,
  417.             final ITable actualTable, final ComparisonColumn[] comparisonCols,
  418.             final FailureHandler failureHandler) throws DataSetException
  419.     {
  420.         final ValueComparer defaultValueComparer = null;
  421.         final Map<String, ValueComparer> columnValueComparers = null;
  422.         try
  423.         {
  424.             compareData(expectedTable, actualTable, comparisonCols,
  425.                     failureHandler, defaultValueComparer, columnValueComparers);
  426.         } catch (final DatabaseUnitException e)
  427.         {
  428.             // not-private method, signature change breaks compatability
  429.             throw new DataSetException(e);
  430.         }
  431.     }

  432.     /**
  433.      * @param expectedTable
  434.      *            {@link ITable} containing all expected results.
  435.      * @param actualTable
  436.      *            {@link ITable} containing all actual results.
  437.      * @param comparisonCols
  438.      *            The columns to be compared, also including the correct
  439.      *            {@link DataType}s for comparison
  440.      * @param failureHandler
  441.      *            The failure handler used if the assert fails because of a data
  442.      *            mismatch. Provides some additional information that may be
  443.      *            useful to quickly identify the rows for which the mismatch
  444.      *            occurred (for example by printing an additional primary key
  445.      *            column). Must not be <code>null</code> at this stage.
  446.      * @param defaultValueComparer
  447.      *            {@link ValueComparer} to use with column value comparisons
  448.      *            when the column name for the table is not in the
  449.      *            columnValueComparers {@link Map}. Can be <code>null</code> and
  450.      *            will default to {@link #getDefaultValueComparer()}.
  451.      * @param columnValueComparers
  452.      *            {@link Map} of {@link ValueComparer}s to use for specific
  453.      *            columns. Key is column name in the table, value is
  454.      *            {@link ValueComparer} to use in comparing expected to actual
  455.      *            column values. Can be <code>null</code> and will default to
  456.      *            using
  457.      *            {@link #getDefaultColumnValueComparerMapForTable(String)} or,
  458.      *            if that is empty, defaultValueComparer for all columns in the
  459.      *            table.
  460.      * @throws DataSetException
  461.      * @since 2.4
  462.      * @since 2.6.0
  463.      */
  464.     protected void compareData(final ITable expectedTable,
  465.             final ITable actualTable, final ComparisonColumn[] comparisonCols,
  466.             final FailureHandler failureHandler,
  467.             final ValueComparer defaultValueComparer,
  468.             final Map<String, ValueComparer> columnValueComparers)
  469.             throws DatabaseUnitException
  470.     {
  471.         log.debug(
  472.                 "compareData(expectedTable={}, actualTable={}, "
  473.                         + "comparisonCols={}, failureHandler={},"
  474.                         + " defaultValueComparer={}, columnValueComparers={})"
  475.                         + " - start",
  476.                 expectedTable, actualTable, comparisonCols, failureHandler,
  477.                 defaultValueComparer, columnValueComparers);

  478.         if (expectedTable == null)
  479.         {
  480.             throw new IllegalArgumentException(
  481.                     "The parameter 'expectedTable' is null");
  482.         }
  483.         if (actualTable == null)
  484.         {
  485.             throw new IllegalArgumentException(
  486.                     "The parameter 'actualTable' is null");
  487.         }
  488.         if (comparisonCols == null)
  489.         {
  490.             throw new IllegalArgumentException(
  491.                     "The parameter 'comparisonCols' is null");
  492.         }
  493.         if (failureHandler == null)
  494.         {
  495.             throw new IllegalArgumentException(
  496.                     "The parameter 'failureHandler' is null");
  497.         }

  498.         final ValueComparer validDefaultValueComparer =
  499.                 determineValidDefaultValueComparer(defaultValueComparer);
  500.         final String expectedTableName =
  501.                 expectedTable.getTableMetaData().getTableName();
  502.         final Map<String, ValueComparer> validColumnValueComparers =
  503.                 determineValidColumnValueComparers(columnValueComparers,
  504.                         expectedTableName);

  505.         // iterate over all rows
  506.         for (int rowNum = 0; rowNum < expectedTable.getRowCount(); rowNum++)
  507.         {
  508.             // iterate over all columns of the current row
  509.             final int columnCount = comparisonCols.length;
  510.             for (int columnNum = 0; columnNum < columnCount; columnNum++)
  511.             {
  512.                 compareData(expectedTable, actualTable, comparisonCols,
  513.                         failureHandler, validDefaultValueComparer,
  514.                         validColumnValueComparers, rowNum, columnNum);
  515.             }
  516.         }
  517.     }

  518.     protected void compareData(final ITable expectedTable,
  519.             final ITable actualTable, final ComparisonColumn[] comparisonCols,
  520.             final FailureHandler failureHandler,
  521.             final ValueComparer defaultValueComparer,
  522.             final Map<String, ValueComparer> columnValueComparers,
  523.             final int rowNum, final int columnNum) throws DatabaseUnitException
  524.     {
  525.         final ComparisonColumn compareColumn = comparisonCols[columnNum];

  526.         final String columnName = compareColumn.getColumnName();
  527.         final DataType dataType = compareColumn.getDataType();

  528.         final Object expectedValue = expectedTable.getValue(rowNum, columnName);
  529.         final Object actualValue = actualTable.getValue(rowNum, columnName);

  530.         // Compare the values
  531.         if (skipCompare(columnName, expectedValue, actualValue))
  532.         {
  533.             log.trace(
  534.                     "skipCompare: ignoring comparison" + " {}={} on column={}",
  535.                     expectedValue, actualValue, columnName);
  536.         } else
  537.         {
  538.             final ValueComparer valueComparer = determineValueComparer(
  539.                     columnName, defaultValueComparer, columnValueComparers);

  540.             log.debug(
  541.                     "compareData: comparing actualValue={}"
  542.                             + " to expectedValue={} with valueComparer={}",
  543.                     actualValue, expectedValue, valueComparer);
  544.             final String failMessage =
  545.                     valueComparer.compare(expectedTable, actualTable, rowNum,
  546.                             columnName, dataType, expectedValue, actualValue);

  547.             failIfNecessary(expectedTable, actualTable, failureHandler, rowNum,
  548.                     columnName, expectedValue, actualValue, failMessage);
  549.         }
  550.     }

  551.     protected void failIfNecessary(final ITable expectedTable,
  552.             final ITable actualTable, final FailureHandler failureHandler,
  553.             final int rowNum, final String columnName,
  554.             final Object expectedValue, final Object actualValue,
  555.             final String failMessage)
  556.     {
  557.         if (failMessage != null)
  558.         {
  559.             final Difference diff = new Difference(expectedTable, actualTable,
  560.                     rowNum, columnName, expectedValue, actualValue,
  561.                     failMessage);

  562.             failureHandler.handle(diff);
  563.         }
  564.     }

  565.     protected ValueComparer determineValueComparer(final String columnName,
  566.             final ValueComparer defaultValueComparer,
  567.             final Map<String, ValueComparer> columnValueComparers)
  568.     {
  569.         ValueComparer valueComparer = columnValueComparers.get(columnName);
  570.         if (valueComparer == null)
  571.         {
  572.             log.debug(
  573.                     "determineValueComparer: using defaultValueComparer='{}'"
  574.                             + " as columnName='{}' not found"
  575.                             + " in columnValueComparers='{}'",
  576.                     defaultValueComparer, columnName, columnValueComparers);
  577.             valueComparer = defaultValueComparer;
  578.         }

  579.         return valueComparer;
  580.     }

  581.     protected ValueComparer determineValidDefaultValueComparer(
  582.             final ValueComparer defaultValueComparer)
  583.     {
  584.         final ValueComparer validValueComparer;

  585.         if (defaultValueComparer == null)
  586.         {
  587.             validValueComparer =
  588.                     valueComparerDefaults.getDefaultValueComparer();
  589.             log.debug(
  590.                     "determineValidDefaultValueComparer:"
  591.                             + " using getDefaultValueComparer()={}"
  592.                             + " as defaultValueComparer={}",
  593.                     validValueComparer, defaultValueComparer);
  594.         } else
  595.         {
  596.             validValueComparer = defaultValueComparer;
  597.         }

  598.         return validValueComparer;
  599.     }

  600.     protected Map<String, Map<String, ValueComparer>> determineValidTableColumnValueComparers(
  601.             final Map<String, Map<String, ValueComparer>> tableColumnValueComparers)
  602.     {
  603.         final Map<String, Map<String, ValueComparer>> validMap;

  604.         if (tableColumnValueComparers == null)
  605.         {
  606.             validMap = valueComparerDefaults
  607.                     .getDefaultTableColumnValueComparerMap();
  608.             log.debug(
  609.                     "determineValidTableColumnValueComparers:"
  610.                             + " using getDefaultTableColumnValueComparerMap()={}"
  611.                             + " as tableColumnValueComparers={}",
  612.                     validMap, tableColumnValueComparers);
  613.         } else
  614.         {
  615.             validMap = tableColumnValueComparers;
  616.         }

  617.         return validMap;
  618.     }

  619.     protected Map<String, ValueComparer> determineValidColumnValueComparers(
  620.             final Map<String, ValueComparer> columnValueComparers,
  621.             final String tableName)
  622.     {
  623.         final Map<String, ValueComparer> validMap;

  624.         if (columnValueComparers == null)
  625.         {
  626.             validMap = valueComparerDefaults
  627.                     .getDefaultColumnValueComparerMapForTable(tableName);
  628.             log.debug(
  629.                     "determineValidColumnValueComparers:"
  630.                             + " using getDefaultValueComparerMap()={}"
  631.                             + " as columnValueComparers={} for tableName={}",
  632.                     validMap, columnValueComparers, tableName);
  633.         } else
  634.         {
  635.             validMap = columnValueComparers;
  636.         }

  637.         return validMap;
  638.     }

  639.     public void setValueComparerDefaults(
  640.             final ValueComparerDefaults valueComparerDefaults)
  641.     {
  642.         this.valueComparerDefaults = valueComparerDefaults;
  643.     }
  644. }