<commit_before>package eu.drus.jpa.unit.fixture.dbunit;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.dbunit.Assertion;
import org.dbunit.DatabaseUnitException;
import org.dbunit.assertion.DiffCollectingFailureHandler;
import org.dbunit.assertion.Difference;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.CompositeTable;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.FilteredDataSet;
import org.dbunit.dataset.FilteredTableMetaData;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.NoSuchTableException;
import org.dbunit.dataset.SortedTable;
import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.filter.IColumnFilter;
import org.dbunit.dataset.filter.IncludeTableFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.drus.jpa.unit.api.JpaUnitException;
import eu.drus.jpa.unit.core.AssertionErrorCollector;

public class DataSetComparator {

    private static final String DIFF_ERROR = "%s | In row %d: expected value of %s \"%s\" but was \"%s\".";

    private static final Logger LOG = LoggerFactory.getLogger(DataSetComparator.class);

    private final ColumnsHolder toExclude;

    private final ColumnsHolder orderBy;

    private final Set<Class<? extends IColumnFilter>> columnFilters;

    private boolean isStrict;

    public DataSetComparator(final String[] orderBy, final String[] toExclude, final boolean isStrict,
            final Set<Class<? extends IColumnFilter>> columnFilters) {
        this.toExclude = new ColumnsHolder(toExclude);
        this.orderBy = new ColumnsHolder(orderBy);
        this.isStrict = isStrict;
        this.columnFilters = columnFilters;
    }

    public void compare(final IDataSet currentDataSet, final IDataSet expectedDataSet, final AssertionErrorCollector errorCollector)
            throws DatabaseUnitException {
        if (expectedDataSet.getTableNames().length == 0) {
            shouldBeEmpty(currentDataSet, errorCollector);
        } else {
            compareContent(currentDataSet, expectedDataSet, errorCollector);
        }
    }

    private void shouldBeEmpty(final IDataSet dataSet, final AssertionErrorCollector errorCollector) throws DatabaseUnitException {
        for (final String tableName : dataSet.getTableNames()) {
            final int rowCount = dataSet.getTable(tableName).getRowCount();
            if (rowCount != 0) {
                errorCollector.collect(tableName + " was expected to be empty, but has <" + rowCount + "> entries.");
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void compareContent(final IDataSet currentDataSet, final IDataSet expectedDataSet, final AssertionErrorCollector errorCollector)
            throws DatabaseUnitException {
        final String[] expectedTableNames = expectedDataSet.getTableNames();
        final FilteredDataSet filteredCurrentDataSet = new FilteredDataSet(new IncludeTableFilter(expectedTableNames), currentDataSet);

        for (final String tableName : expectedTableNames) {
            try {
                final List<String> columnsForSorting = defineColumnsForSorting(filteredCurrentDataSet, expectedDataSet, tableName);

                final ITable table = filteredCurrentDataSet.getTable(tableName);
                final ITable expectedTable = sort(new TableWrapper(expectedDataSet.getTable(tableName), table.getTableMetaData()),
                        columnsForSorting);
                final ITable currentTable = sort(table, columnsForSorting);

                final List<String> columnsToIgnore = extractColumnsToBeIgnored(expectedDataSet.getTable(tableName), table);

                final String[] toBeIgnored = columnsToIgnore.toArray(new String[columnsToIgnore.size()]);

                final ITable expectedTableWithFilteredColumns = filter(expectedTable, toBeIgnored);
                final ITable actualTableWithFilteredColumns = filter(currentTable, toBeIgnored);

                final DiffCollectingFailureHandler diffCollector = new DiffCollectingFailureHandler();
                Assertion.assertEquals(expectedTableWithFilteredColumns, actualTableWithFilteredColumns, diffCollector);

                collectErrors(errorCollector, diffCollector.getDiffList());
            } catch (final NoSuchTableException e) {
                final int rowCount = expectedDataSet.getTable(tableName).getRowCount();
                errorCollector.collect(tableName + " was expected to be present and to contain <" + rowCount + "> entries, but not found.");
            }
        }

        if (isStrict) {
            final List<String> currentTableNames = new ArrayList<>(Arrays.asList(currentDataSet.getTableNames()));
            currentTableNames.removeAll(Arrays.asList(expectedTableNames));
            for (final String notExpectedTableName : currentTableNames) {
                final int rowCount = currentDataSet.getTable(notExpectedTableName).getRowCount();
                errorCollector.collect(notExpectedTableName + " was not expected, but is present and contains <" + rowCount + "> entries.");
            }
        }
    }

    private List<String> defineColumnsForSorting(final IDataSet currentDataSet, final IDataSet expectedDataSet, final String tableName)
            throws DataSetException {

        final List<String> additionalColumns = additionalColumnsForSorting(expectedDataSet.getTable(tableName),
                currentDataSet.getTable(tableName));<commit_msg>Fixed DataSetComparator not to leak the DbUnit exceptions<commit_after>package eu.drus.jpa.unit.fixture.dbunit;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.dbunit.Assertion;
import org.dbunit.DatabaseUnitException;
import org.dbunit.assertion.DbComparisonFailure;
import org.dbunit.assertion.DiffCollectingFailureHandler;
import org.dbunit.assertion.Difference;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.CompositeTable;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.FilteredDataSet;
import org.dbunit.dataset.FilteredTableMetaData;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.NoSuchTableException;
import org.dbunit.dataset.SortedTable;
import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.filter.IColumnFilter;
import org.dbunit.dataset.filter.IncludeTableFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.drus.jpa.unit.api.JpaUnitException;
import eu.drus.jpa.unit.core.AssertionErrorCollector;

public class DataSetComparator {

    private static final String DIFF_ERROR = "%s | In row %d: expected value of %s \"%s\" but was \"%s\".";

    private static final Logger LOG = LoggerFactory.getLogger(DataSetComparator.class);

    private final ColumnsHolder toExclude;

    private final ColumnsHolder orderBy;

    private final Set<Class<? extends IColumnFilter>> columnFilters;

    private boolean isStrict;

    public DataSetComparator(final String[] orderBy, final String[] toExclude, final boolean isStrict,
            final Set<Class<? extends IColumnFilter>> columnFilters) {
        this.toExclude = new ColumnsHolder(toExclude);
        this.orderBy = new ColumnsHolder(orderBy);
        this.isStrict = isStrict;
        this.columnFilters = columnFilters;
    }

    public void compare(final IDataSet currentDataSet, final IDataSet expectedDataSet, final AssertionErrorCollector errorCollector)
            throws DatabaseUnitException {
        if (expectedDataSet.getTableNames().length == 0) {
            shouldBeEmpty(currentDataSet, errorCollector);
        } else {
            compareContent(currentDataSet, expectedDataSet, errorCollector);
        }
    }

    private void shouldBeEmpty(final IDataSet dataSet, final AssertionErrorCollector errorCollector) throws DatabaseUnitException {
        for (final String tableName : dataSet.getTableNames()) {
            final int rowCount = dataSet.getTable(tableName).getRowCount();
            if (rowCount != 0) {
                errorCollector.collect(tableName + " was expected to be empty, but has <" + rowCount + "> entries.");
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void compareContent(final IDataSet currentDataSet, final IDataSet expectedDataSet, final AssertionErrorCollector errorCollector)
            throws DatabaseUnitException {
        final String[] expectedTableNames = expectedDataSet.getTableNames();
        final FilteredDataSet filteredCurrentDataSet = new FilteredDataSet(new IncludeTableFilter(expectedTableNames), currentDataSet);

        for (final String tableName : expectedTableNames) {
            try {
                final List<String> columnsForSorting = defineColumnsForSorting(filteredCurrentDataSet, expectedDataSet, tableName);

                final ITable table = filteredCurrentDataSet.getTable(tableName);
                final ITable expectedTable = sort(new TableWrapper(expectedDataSet.getTable(tableName), table.getTableMetaData()),
                        columnsForSorting);
                final ITable currentTable = sort(table, columnsForSorting);

                final List<String> columnsToIgnore = extractColumnsToBeIgnored(expectedDataSet.getTable(tableName), table);

                final String[] toBeIgnored = columnsToIgnore.toArray(new String[columnsToIgnore.size()]);

                final ITable expectedTableWithFilteredColumns = filter(expectedTable, toBeIgnored);
                final ITable actualTableWithFilteredColumns = filter(currentTable, toBeIgnored);

                final DiffCollectingFailureHandler diffCollector = new DiffCollectingFailureHandler();
                Assertion.assertEquals(expectedTableWithFilteredColumns, actualTableWithFilteredColumns, diffCollector);

                collectErrors(errorCollector, diffCollector.getDiffList());
            } catch (final NoSuchTableException e) {
                final int rowCount = expectedDataSet.getTable(tableName).getRowCount();
                errorCollector.collect(tableName + " was expected to be present and to contain <" + rowCount + "> entries, but not found.");
            } catch (final DbComparisonFailure e) {
                errorCollector.collect(e.getMessage());
            }
        }

        if (isStrict) {
            final List<String> currentTableNames = new ArrayList<>(Arrays.asList(currentDataSet.getTableNames()));
            currentTableNames.removeAll(Arrays.asList(expectedTableNames));
            for (final String notExpectedTableName : currentTableNames) {
                final int rowCount = currentDataSet.getTable(notExpectedTableName).getRowCount();
                if (rowCount > 0) {
                    errorCollector
                            .collect(notExpectedTableName + " was not expected, but is present and contains <" + rowCount + "> entries.");
                }
            }
        }
    }

    private List<String> defineColumnsForSorting(final IDataSet currentDataSet, final IDataSet expectedDataSet, final String tableName)
            throws DataSetException {

        final List<String> additionalColumns = additionalColumnsForSorting(expectedDataSet.getTable(tableName),
                currentDataSet.getTable(tableName));
{'fraction_non_alphanumeric': 0.08138528138528138, 'fraction_numerical': 0.0007792207792207792, 'mean_word_length': 3.4928043562816025, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3319082', 'n_tokens_mistral': 2963, 'n_tokens_neox': 2970, 'n_words': 671}