From 631a53f37d92c303adb6bdb07b47de50c1c02b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Tue, 27 Nov 2012 21:16:04 +0100 Subject: [PATCH 01/15] Improved the logging statements to have all necessary information available to resolve the issue. --- .../arquillian/persistence/dbunit/DataSetComparator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java index 1aa5f9f5..953a4236 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java @@ -180,7 +180,8 @@ private List additionalColumnsForSorting(final ITable expectedTableState } catch (DataSetException e) { - throw new DBUnitDataSetHandlingException("Unable to resolve columns", e); + throw new DBUnitDataSetHandlingException("Unable to resolve columns in table " + + expectedTableState.getTableMetaData().getTableName(), e); } return columnsForSorting; @@ -207,7 +208,7 @@ private List extractColumnsToBeIgnored(final ITable expectedTableState, if (!nonExistingColumns.isEmpty()) { log.warning("Columns which are specified to be filtered out [" + Arrays.toString(nonExistingColumns.toArray()) - + "] are not existing in the table."); + + "] are not existing in the table " + expectedTableState.getTableMetaData().getTableName()); } return columnsToIgnore; } From 9afa40d5694724eb03912fd889faa43735ba501d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Tue, 27 Nov 2012 21:54:17 +0100 Subject: [PATCH 02/15] When we define columns for sorting in the orderBy we do not add other columns anymore. When we define global column names and this columns is not available on all tables (for example join tables), we log a warning but do not fail comparing the dataset. --- .../persistence/dbunit/DataSetComparator.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java index 953a4236..413d635e 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DataSetComparator.java @@ -21,11 +21,7 @@ import static org.jboss.arquillian.persistence.dbunit.DataSetUtils.extractColumnsNotSpecifiedInExpectedDataSet; import static org.jboss.arquillian.persistence.dbunit.DataSetUtils.extractNonExistingColumns; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.logging.Logger; import org.dbunit.Assertion; @@ -144,17 +140,39 @@ private List defineColumnsForSorting(IDataSet currentDataSet, IDataSet e throws DataSetException { final List columnsForSorting = new ArrayList(); - columnsForSorting.addAll(orderBy.global); + columnsForSorting.addAll(existingColumnsForTable(expectedDataSet, tableName, orderBy.global)); final List columsPerTable = orderBy.columnsPerTable.get(tableName); if (columsPerTable != null) { columnsForSorting.addAll(columsPerTable); } - columnsForSorting.addAll(additionalColumnsForSorting(expectedDataSet.getTable(tableName), - currentDataSet.getTable(tableName))); + + // Add all columns if none are defined in orderBy + if (columnsForSorting.isEmpty()) { + columnsForSorting.addAll(additionalColumnsForSorting(expectedDataSet.getTable(tableName), + currentDataSet.getTable(tableName))); + } + return columnsForSorting; } + private Collection existingColumnsForTable(IDataSet set, String tableName, List expectedColumns) throws DataSetException + { + Set existingColumns = new HashSet(); + + Collection tableColumns = extractColumnNames(set.getTable(tableName).getTableMetaData().getColumns()); + + for (String currentColumn : expectedColumns) { + if (tableColumns.contains(currentColumn.toLowerCase())) { + existingColumns.add(currentColumn.toLowerCase()); + } else { + log.warning("Column " + currentColumn.toLowerCase() + " in Table " + tableName + " was set to be an ordering column but does not exist in this table. Ignoring it. Consider using [TABLENAME.COLUMNNAME]"); + } + } + + return existingColumns; + } + private static String[] toArray(final List list) { return list.toArray(new String[list.size()]); From 69d97684ffda9fc4a979dd42fe02a86411e313c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Tue, 27 Nov 2012 22:36:54 +0100 Subject: [PATCH 03/15] First skeleton of the column sorting fix --- .../persistence/dbunit/dataset/Table.java | 8 ++-- .../dbunit/dataset/json/DataSetProducer.java | 39 ++++++++++++------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/Table.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/Table.java index 7cef8233..fca74720 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/Table.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/Table.java @@ -17,6 +17,8 @@ */ package org.jboss.arquillian.persistence.dbunit.dataset; +import org.dbunit.dataset.Column; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -35,7 +37,7 @@ public class Table { private final String tableName; - private final Set columns = new HashSet(); + private final Set columns = new HashSet(); private final List rows = new ArrayList(); @@ -49,7 +51,7 @@ public void addRows(Collection rows) this.rows.addAll(rows); } - public void addColumns(Collection columns) + public void addColumns(Collection columns) { this.columns.addAll(columns); } @@ -59,7 +61,7 @@ public String getTableName() return tableName; } - public Set getColumns() + public Set getColumns() { return Collections.unmodifiableSet(columns); } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java index be0274df..f0532f81 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java @@ -97,18 +97,7 @@ public void produce() throws DataSetException private ITableMetaData createTableMetaData(Table table) { - return new DefaultTableMetaData(table.getTableName(), createColumns(table.getColumns())); - } - - private Column[] createColumns(Collection columnNames) - { - final List columns = new ArrayList(); - for (String columnName : columnNames) - { - Column column = new Column(columnName, DataType.UNKNOWN); - columns.add(column); - } - return columns.toArray(new Column[columns.size()]); + return new DefaultTableMetaData(table.getTableName(), table.getColumns().toArray(new Column[table.getColumns().size()])); } private List createTables(Map>> jsonStructure) @@ -134,16 +123,36 @@ private Collection extractRows(List> rows) return extractedRows; } - private Collection extractColumns(List> rows) + private Collection extractColumns(List> rows) { - final Set columns = new HashSet(); + final Set columns = new HashSet(); for (Map row : rows) { - columns.addAll(row.keySet()); + columns.addAll(extractColumnsFromDatasetRow(row)); } return columns; } + private Collection extractColumnsFromDatasetRow(Map row) + { + final Set columns = new HashSet(); + for (Map.Entry currentEntry : row.entrySet()) { + String columnName = currentEntry.getKey(); + Object value = currentEntry.getValue(); + DataType dataType = null; + + if (value instanceof Integer) { + dataType = DataType.INTEGER; + } else { + dataType = DataType.VARCHAR; + } + + columns.add(new Column(columnName, dataType)); + } + + return columns; + } + public boolean isCaseSensitiveTableNames() { return caseSensitiveTableNames; From 4f7afa3e30d83e059f6f44f14fe87577e7e8896f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Wed, 28 Nov 2012 22:51:41 +0100 Subject: [PATCH 04/15] Added the JsonDataTypeConverter and use it to determine the datatype of a column. Needed to fix the Yaml thing too, but do not know if it works there. --- .../dbunit/dataset/json/DataSetProducer.java | 6 +- .../dataset/json/JsonDataTypeConverter.java | 78 +++++++++++++++++++ .../dataset/yaml/YamlDataSetProducer.java | 28 ++++++- .../json/JsonDataTypeConverterTest.java | 37 +++++++++ 4 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java create mode 100644 impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java index f0532f81..9febbce6 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java @@ -141,11 +141,7 @@ private Collection extractColumnsFromDatasetRow(Map row) Object value = currentEntry.getValue(); DataType dataType = null; - if (value instanceof Integer) { - dataType = DataType.INTEGER; - } else { - dataType = DataType.VARCHAR; - } + dataType = new JsonDataTypeConverter().convertJSonDataTypeToDBUnitDataType(value.getClass()); columns.add(new Column(columnName, dataType)); } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java new file mode 100644 index 00000000..069d0145 --- /dev/null +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java @@ -0,0 +1,78 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.arquillian.persistence.dbunit.dataset.json; + + +import org.dbunit.dataset.datatype.DataType; + +import java.math.BigInteger; +import java.util.ArrayList; + +public class JsonDataTypeConverter { + + public DataType convertJSonDataTypeToDBUnitDataType(Class clazz, boolean containsTimestampCharachters) + { + return JsonDataTypes.dataTypeForClass(clazz, containsTimestampCharachters); + } + + public boolean containsTimestampCharacters(String value) + { + boolean constainsTimestampCharacters = false; + + // TODO REGEX PATTERN TO CHECK IF THE VALUE IS A TIMESTAMP + + return constainsTimestampCharacters; + } + + private static enum JsonDataTypes { + STRING(String.class, DataType.VARCHAR, false), + INTEGER(Integer.class, DataType.DECIMAL, false), + LONG(Long.class,DataType.DECIMAL, false), + BIGINTEGER(BigInteger.class, DataType.DECIMAL, false), + UNKNOWN(ArrayList.class, DataType.UNKNOWN, false), // value == [null], we have no data type information available + TIMESTAMP(String.class, DataType.TIMESTAMP, true); + + private Class clazz; + + private DataType dataType; + + private boolean containsTimestampCharacters = false; + + private JsonDataTypes(Class clazz, DataType dataType, boolean containsTimestampCharacters) + { + this.clazz = clazz; + this.dataType = dataType; + this.containsTimestampCharacters = containsTimestampCharacters; + } + + public static DataType dataTypeForClass(Class clazz, boolean containsTimestampCharacters) + { + DataType dataType = DataType.VARCHAR; + + for (JsonDataTypes currentDataType : JsonDataTypes.values()) + { + if (currentDataType.clazz.equals(clazz) && currentDataType.containsTimestampCharacters == containsTimestampCharacters) + { + dataType = currentDataType.dataType; + } + } + + return dataType; + } + } +} diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java index a1c80c4a..3d58f39d 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java @@ -123,7 +123,7 @@ protected void addImplicitResolvers() private ITableMetaData createTableMetaData(Table table) { - return new DefaultTableMetaData(table.getTableName(), createColumns(table.getColumns())); + return new DefaultTableMetaData(table.getTableName(), table.getColumns().toArray(new Column[table.getColumns().size()])); } private Column[] createColumns(Collection columnNames) @@ -160,16 +160,36 @@ private Collection extractRows(List> rows) return extractedRows; } - private Collection extractColumns(List> rows) + private Collection extractColumns(List> rows) { - final Set columns = new HashSet(); + final Set columns = new HashSet(); for (Map row : rows) { - columns.addAll(row.keySet()); + columns.addAll(extractColumnsFromDatasetRow(row)); } return columns; } + private Collection extractColumnsFromDatasetRow(Map row) + { + final Set columns = new HashSet(); + for (Map.Entry currentEntry : row.entrySet()) { + String columnName = currentEntry.getKey(); + Object value = currentEntry.getValue(); + DataType dataType = null; + + if (value instanceof Integer) { + dataType = DataType.INTEGER; + } else { + dataType = DataType.VARCHAR; + } + + columns.add(new Column(columnName, dataType)); + } + + return columns; + } + // Getters & Setters public boolean isCaseSensitiveTableNames() diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java new file mode 100644 index 00000000..96beacc2 --- /dev/null +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java @@ -0,0 +1,37 @@ +package org.jboss.arquillian.persistence.dbunit.dataset.json; + + +import org.dbunit.dataset.datatype.DataType; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class JsonDataTypeConverterTest { + + private JsonDataTypeConverter converter = null; + + @Before + public void setup() + { + converter = new JsonDataTypeConverter(); + } + + @Test + public void withInteger() + { + assertEquals("DataType is not the expected one", DataType.INTEGER, converter.convertJSonDataTypeToDBUnitDataType(Integer.class)); + } + + @Test + public void withNull() + { + assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType(null)); + } + + @Test + public void unkownClass() + { + assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType(Before.class)); + } +} From ec8030f41e41a58d0be60d5454e38a6158d8162a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Fri, 30 Nov 2012 07:13:59 +0100 Subject: [PATCH 05/15] Fixed the data type detection for special data types like Timestamp which will be reported as Strings by Jackson as well. But they should be end up as - for example - data type TIMESTAMP. This detection is done by an additional regex pattern. --- .../dbunit/dataset/json/DataSetProducer.java | 2 +- .../dataset/json/JsonDataTypeConverter.java | 59 ++++++++++++------- .../json/JsonDataTypeConverterTest.java | 29 ++++++++- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java index 9febbce6..d3e4e005 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java @@ -141,7 +141,7 @@ private Collection extractColumnsFromDatasetRow(Map row) Object value = currentEntry.getValue(); DataType dataType = null; - dataType = new JsonDataTypeConverter().convertJSonDataTypeToDBUnitDataType(value.getClass()); + dataType = new JsonDataTypeConverter().convertJSonDataTypeToDBUnitDataType(value, value.getClass()); columns.add(new Column(columnName, dataType)); } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java index 069d0145..f33d6685 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java @@ -22,51 +22,53 @@ import java.math.BigInteger; import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class JsonDataTypeConverter { - public DataType convertJSonDataTypeToDBUnitDataType(Class clazz, boolean containsTimestampCharachters) + public DataType convertJSonDataTypeToDBUnitDataType(Object value, Class clazz) { - return JsonDataTypes.dataTypeForClass(clazz, containsTimestampCharachters); - } - - public boolean containsTimestampCharacters(String value) - { - boolean constainsTimestampCharacters = false; - - // TODO REGEX PATTERN TO CHECK IF THE VALUE IS A TIMESTAMP - - return constainsTimestampCharacters; + return JsonDataTypes.dataTypeForClass(value, clazz); } + /** + * The regex pattern differentiates between the same data types reported by Jackson and the real data type to be applied + * for DBUnit so the comparison with the real data type read from the metadata of the database by DBUnit. Because we have + * no data type information available in JSON, we have to perform a best guess. For example, a normal String and a Timestamp + * are reported both as data type String and whould end up as a VARCHAR. The differentiation is done by an additional regex pattern + * which will detect the real datatypes. + */ private static enum JsonDataTypes { - STRING(String.class, DataType.VARCHAR, false), - INTEGER(Integer.class, DataType.DECIMAL, false), - LONG(Long.class,DataType.DECIMAL, false), - BIGINTEGER(BigInteger.class, DataType.DECIMAL, false), - UNKNOWN(ArrayList.class, DataType.UNKNOWN, false), // value == [null], we have no data type information available - TIMESTAMP(String.class, DataType.TIMESTAMP, true); + STRING(String.class, DataType.VARCHAR, "[^-|:]*"), + INTEGER(Integer.class, DataType.DECIMAL, "\\d*"), + LONG(Long.class,DataType.DECIMAL, "\\d*"), + BIGINTEGER(BigInteger.class, DataType.DECIMAL, "\\d*"), + UNKNOWN(ArrayList.class, DataType.UNKNOWN, ".*"), // value == [null], we have no data type information available + TIMESTAMP(String.class, DataType.TIMESTAMP, "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}"); private Class clazz; private DataType dataType; - private boolean containsTimestampCharacters = false; + private String regexPattern; - private JsonDataTypes(Class clazz, DataType dataType, boolean containsTimestampCharacters) + private JsonDataTypes(Class clazz, DataType dataType, String regexPattern) { this.clazz = clazz; this.dataType = dataType; - this.containsTimestampCharacters = containsTimestampCharacters; + this.regexPattern = regexPattern; } - public static DataType dataTypeForClass(Class clazz, boolean containsTimestampCharacters) + public static DataType dataTypeForClass(Object value, Class clazz) { DataType dataType = DataType.VARCHAR; for (JsonDataTypes currentDataType : JsonDataTypes.values()) { - if (currentDataType.clazz.equals(clazz) && currentDataType.containsTimestampCharacters == containsTimestampCharacters) + boolean matches = match(value, currentDataType.regexPattern); + + if (currentDataType.clazz.equals(clazz) && matches) { dataType = currentDataType.dataType; } @@ -74,5 +76,18 @@ public static DataType dataTypeForClass(Class clazz, boolean containsTimestampCh return dataType; } + + public static boolean match(Object value, String regexPattern) + { + boolean matches = false; + + if (null != regexPattern && null != value) + { + String stringValue = value.toString(); + matches = Pattern.matches(regexPattern, stringValue); + } + + return matches; + } } } diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java index 96beacc2..9f1a1219 100644 --- a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java @@ -5,6 +5,8 @@ import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; + import static org.junit.Assert.assertEquals; public class JsonDataTypeConverterTest { @@ -20,18 +22,39 @@ public void setup() @Test public void withInteger() { - assertEquals("DataType is not the expected one", DataType.INTEGER, converter.convertJSonDataTypeToDBUnitDataType(Integer.class)); + assertEquals("DataType is not the expected one", DataType.DECIMAL, converter.convertJSonDataTypeToDBUnitDataType(Integer.valueOf(1), Integer.class)); } + @Test + public void withString() + { + assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType("Good morning", String.class)); + } @Test public void withNull() { - assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType(null)); + assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType(null, null)); } @Test public void unkownClass() { - assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType(Before.class)); + assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType("Fred Unkown", Before.class)); + } + + @Test + public void specialValueLikeDBUnitNull() + { + // DBUnit placeholder [null] creates an empty ArrayList when parsed by Jackson. In order to compare against the real/correct datatype + // from the database, we have to set it to unkown in order to prevent DBUnit to fail because the data types are not the same. + ArrayList list = new ArrayList(); + assertEquals("DataType is not the expected one", DataType.UNKNOWN, converter.convertJSonDataTypeToDBUnitDataType(list, ArrayList.class)); + } + + @Test + public void withTimestamp() + { + // A Timestamp is also reported as data type String by Jackson. We have to differenciate normal Strings and Timestamps + assertEquals("Datatype is not the expected one", DataType.TIMESTAMP, converter.convertJSonDataTypeToDBUnitDataType("2012-12-12 00:00:00", String.class)); } } From 4e2aa977b066e941962fa124aa4fe0d23143a3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 08:36:27 +0100 Subject: [PATCH 06/15] Fixed the timestamp with milliseconds or without milliseconds. --- .../dbunit/dataset/json/JsonDataTypeConverter.java | 2 +- .../dbunit/dataset/json/JsonDataTypeConverterTest.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java index f33d6685..2a87d9bc 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java @@ -45,7 +45,7 @@ private static enum JsonDataTypes { LONG(Long.class,DataType.DECIMAL, "\\d*"), BIGINTEGER(BigInteger.class, DataType.DECIMAL, "\\d*"), UNKNOWN(ArrayList.class, DataType.UNKNOWN, ".*"), // value == [null], we have no data type information available - TIMESTAMP(String.class, DataType.TIMESTAMP, "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}"); + TIMESTAMP(String.class, DataType.TIMESTAMP, "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}[\\.\\d]*"); private Class clazz; diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java index 9f1a1219..347e0968 100644 --- a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java @@ -57,4 +57,11 @@ public void withTimestamp() // A Timestamp is also reported as data type String by Jackson. We have to differenciate normal Strings and Timestamps assertEquals("Datatype is not the expected one", DataType.TIMESTAMP, converter.convertJSonDataTypeToDBUnitDataType("2012-12-12 00:00:00", String.class)); } + + @Test + public void withTimestampMilliseconds() + { + // A Timestamp is also reported as data type String by Jackson. We have to differenciate normal Strings and Timestamps + assertEquals("Datatype is not the expected one", DataType.TIMESTAMP, converter.convertJSonDataTypeToDBUnitDataType("2012-12-12 00:00:00.425", String.class)); + } } From ed5a9eb263ad9e91dc9c5df58863231c5499a4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 17:02:38 +0100 Subject: [PATCH 07/15] Introduces a database data type mapper where the Json Data Types are mapped to the data types of the specific database. For this to happen, the DBUnitConfiguration is used to get the DataTypeFactory (database specific). --- .../FileSqlScriptResourceDescriptor.java | 3 +- .../InlineSqlScriptResourceDescriptor.java | 4 +- .../data/descriptor/ResourceDescriptor.java | 4 +- .../TextFileResourceDescriptor.java | 4 +- .../persistence/dbunit/DBUnitDataHandler.java | 4 +- ...DBUnitPersistenceTestLifecycleHandler.java | 112 +++++++++--------- .../descriptor/DataSetResourceDescriptor.java | 5 +- .../dbunit/dataset/DataSetBuilder.java | 9 +- .../dbunit/dataset/json/DatabaseDataType.java | 46 +++++++ .../dbunit/dataset/json/JsonDataSet.java | 17 +-- .../dataset/json/JsonDataSetProducer.java | 5 +- .../dbunit/dataset/json/JsonDataType.java | 52 ++++++++ .../dataset/json/JsonDataTypeConverter.java | 84 ++++++------- .../dbunit/DataSetComparatorTest.java | 24 +++- .../dbunit/dataset/json/JsonDataSetTest.java | 22 +++- .../json/JsonDataTypeConverterTest.java | 8 +- .../data/DataContentVerifier.java | 2 +- 17 files changed, 265 insertions(+), 140 deletions(-) create mode 100644 impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java create mode 100644 impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/FileSqlScriptResourceDescriptor.java b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/FileSqlScriptResourceDescriptor.java index 780b2bc6..a71c7862 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/FileSqlScriptResourceDescriptor.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/FileSqlScriptResourceDescriptor.java @@ -18,6 +18,7 @@ package org.jboss.arquillian.persistence.core.data.descriptor; import org.jboss.arquillian.persistence.core.data.script.ScriptLoader; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; /** * @@ -35,7 +36,7 @@ public FileSqlScriptResourceDescriptor(String location) } @Override - public String getContent() + public String getContent(DBUnitConfiguration configuration) { return ScriptLoader.loadScript(getLocation()); } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/InlineSqlScriptResourceDescriptor.java b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/InlineSqlScriptResourceDescriptor.java index 23008d67..587255c7 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/InlineSqlScriptResourceDescriptor.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/InlineSqlScriptResourceDescriptor.java @@ -17,6 +17,8 @@ */ package org.jboss.arquillian.persistence.core.data.descriptor; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; + /** * * Inline SQL script descriptor. @@ -36,7 +38,7 @@ public InlineSqlScriptResourceDescriptor(String content) } @Override - public String getContent() + public String getContent(DBUnitConfiguration configuration) { return content; } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/ResourceDescriptor.java b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/ResourceDescriptor.java index 6435ef75..78b9e635 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/ResourceDescriptor.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/ResourceDescriptor.java @@ -17,6 +17,8 @@ */ package org.jboss.arquillian.persistence.core.data.descriptor; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; + /** * Describes resource attributes such as it's location in classpath * and format. @@ -35,7 +37,7 @@ public ResourceDescriptor(String location) this.location = location; } - public abstract T getContent(); + public abstract T getContent(DBUnitConfiguration configuration); public String getLocation() { diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/TextFileResourceDescriptor.java b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/TextFileResourceDescriptor.java index 9365cb5c..78e63ac9 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/TextFileResourceDescriptor.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/core/data/descriptor/TextFileResourceDescriptor.java @@ -17,6 +17,8 @@ */ package org.jboss.arquillian.persistence.core.data.descriptor; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; + import java.io.InputStream; import java.util.Scanner; @@ -36,7 +38,7 @@ public TextFileResourceDescriptor(String location) } @Override - public String getContent() + public String getContent(DBUnitConfiguration configuration) { final InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(getLocation()); return new Scanner(inputStream).useDelimiter("\\A").next(); diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java index 03389312..10f45364 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java @@ -115,7 +115,7 @@ public void cleanupUsingScript(@Observes CleanupDataUsingScript cleanupDataUsing { for (SqlScriptResourceDescriptor scriptDescriptor : cleanupDataUsingScriptEvent.getDescriptors()) { - final String script = scriptDescriptor.getContent(); + final String script = scriptDescriptor.getContent(dbunitConfigurationInstance.get()); executeScript(script); } } @@ -124,7 +124,7 @@ public void executeScripts(@Observes ExecuteScripts executeScriptsEvent) { for (SqlScriptResourceDescriptor scriptDescriptor : executeScriptsEvent.getDescriptors()) { - final String script = scriptDescriptor.getContent(); + final String script = scriptDescriptor.getContent(dbunitConfigurationInstance.get()); executeScript(script); } } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitPersistenceTestLifecycleHandler.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitPersistenceTestLifecycleHandler.java index f23ff03d..92720724 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitPersistenceTestLifecycleHandler.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitPersistenceTestLifecycleHandler.java @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jboss.arquillian.persistence.dbunit; - +package org.jboss.arquillian.persistence.dbunit; + import java.lang.reflect.Method; import java.sql.Connection; import java.util.Collection; @@ -48,36 +48,36 @@ import org.jboss.arquillian.test.spi.annotation.ClassScoped; import org.jboss.arquillian.test.spi.annotation.TestScoped; import org.jboss.arquillian.test.spi.event.suite.TestEvent; - -/** - * - * @author Bartosz Majsak - * - */ -public class DBUnitPersistenceTestLifecycleHandler -{ - - @Inject - private Instance dataSourceInstance; + +/** + * + * @author Bartosz Majsak + * + */ +public class DBUnitPersistenceTestLifecycleHandler +{ + + @Inject + private Instance dataSourceInstance; @Inject private Instance metadataExtractorInstance; @Inject private Instance dbUnitConfigurationInstance; - - @Inject @ClassScoped - private InstanceProducer databaseConnectionProducer; - - @Inject @TestScoped + + @Inject @ClassScoped + private InstanceProducer databaseConnectionProducer; + + @Inject @TestScoped private InstanceProducer dataSetRegisterProducer; @Inject - private Instance persistenceExtensionFeatureResolverInstance; + private Instance persistenceExtensionFeatureResolverInstance; - // ------------------------------------------------------------------------------------------------ - // Intercepting data handling events - // ------------------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------------------ + // Intercepting data handling events + // ------------------------------------------------------------------------------------------------ public void provideDatabaseConnectionAroundBeforePersistenceTest(@Observes(precedence = 100000) EventContext context) { @@ -89,7 +89,7 @@ public void provideDatabaseConnectionAroundAfterPersistenceTest(@Observes(preced provideDatabaseConnection(context); } - public void createDatasets(@Observes(precedence = 1000) EventContext context) + public void createDatasets(@Observes(precedence = 1000) EventContext context) { final Method testMethod = context.getEvent().getTestMethod(); @@ -105,7 +105,7 @@ public void createDatasets(@Observes(precedence = 1000) EventContext context closeDatabaseConnection(); } } - + private void createDatabaseConnection() { @@ -160,7 +160,7 @@ private void createDatabaseConnection() { throw new DBUnitInitializationException("Unable to initialize database connection for DBUnit module.", e); } - } + } private void closeDatabaseConnection() { @@ -177,36 +177,36 @@ private void closeDatabaseConnection() throw new DBUnitConnectionException("Unable to close connection.", e); } } - - private void createInitialDataSets(Collection dataSetDescriptors) - { - DataSetRegister dataSetRegister = getOrCreateDataSetRegister(); - for (DataSetResourceDescriptor dataSetDescriptor : dataSetDescriptors) - { - dataSetRegister.addInitial(dataSetDescriptor.getContent()); - } - dataSetRegisterProducer.set(dataSetRegister); - } - - private void createExpectedDataSets(Collection dataSetDescriptors) - { - DataSetRegister dataSetRegister = getOrCreateDataSetRegister(); - for (DataSetResourceDescriptor dataSetDescriptor : dataSetDescriptors) - { - dataSetRegister.addExpected(dataSetDescriptor.getContent()); - } - dataSetRegisterProducer.set(dataSetRegister); - } - - private DataSetRegister getOrCreateDataSetRegister() - { - DataSetRegister dataSetRegister = dataSetRegisterProducer.get(); - if (dataSetRegister == null) - { - dataSetRegister = new DataSetRegister(); - } - return dataSetRegister; + + private void createInitialDataSets(Collection dataSetDescriptors) + { + DataSetRegister dataSetRegister = getOrCreateDataSetRegister(); + for (DataSetResourceDescriptor dataSetDescriptor : dataSetDescriptors) + { + dataSetRegister.addInitial(dataSetDescriptor.getContent(dbUnitConfigurationInstance.get())); + } + dataSetRegisterProducer.set(dataSetRegister); + } + + private void createExpectedDataSets(Collection dataSetDescriptors) + { + DataSetRegister dataSetRegister = getOrCreateDataSetRegister(); + for (DataSetResourceDescriptor dataSetDescriptor : dataSetDescriptors) + { + dataSetRegister.addExpected(dataSetDescriptor.getContent(dbUnitConfigurationInstance.get())); + } + dataSetRegisterProducer.set(dataSetRegister); + } + + private DataSetRegister getOrCreateDataSetRegister() + { + DataSetRegister dataSetRegister = dataSetRegisterProducer.get(); + if (dataSetRegister == null) + { + dataSetRegister = new DataSetRegister(); + } + return dataSetRegister; } -} +} diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/data/descriptor/DataSetResourceDescriptor.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/data/descriptor/DataSetResourceDescriptor.java index fc90a23c..925bd562 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/data/descriptor/DataSetResourceDescriptor.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/data/descriptor/DataSetResourceDescriptor.java @@ -19,6 +19,7 @@ import org.dbunit.dataset.IDataSet; import org.jboss.arquillian.persistence.core.data.descriptor.ResourceDescriptor; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.jboss.arquillian.persistence.dbunit.dataset.DataSetBuilder; @@ -41,9 +42,9 @@ public DataSetResourceDescriptor(String location, Format format) } @Override - public IDataSet getContent() + public IDataSet getContent(DBUnitConfiguration configuration) { - return DataSetBuilder.builderFor(format).build(location); + return DataSetBuilder.builderFor(format).build(location, configuration); } @Override diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/DataSetBuilder.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/DataSetBuilder.java index e52519fd..e4e9465f 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/DataSetBuilder.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/DataSetBuilder.java @@ -26,6 +26,7 @@ import org.dbunit.dataset.ReplacementDataSet; import org.dbunit.dataset.excel.XlsDataSet; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.jboss.arquillian.persistence.dbunit.data.descriptor.Format; import org.jboss.arquillian.persistence.dbunit.dataset.json.JsonDataSet; import org.jboss.arquillian.persistence.dbunit.dataset.xml.DtdResolver; @@ -48,7 +49,7 @@ private DataSetBuilder(Format format) this.format = format; } - public IDataSet build(final String file) + public IDataSet build(final String file, DBUnitConfiguration configuration) { IDataSet dataSet = null; try @@ -65,7 +66,7 @@ public IDataSet build(final String file) dataSet = loadYamlDataSet(file); break; case JSON: - dataSet = loadJsonDataSet(file); + dataSet = loadJsonDataSet(file, configuration); break; default: throw new DBUnitInitializationException("Unsupported data type " + format); @@ -120,10 +121,10 @@ private XlsDataSet loadExcelDataSet(final String file) throws IOException, DataS return new XlsDataSet(inputStream); } - private JsonDataSet loadJsonDataSet(final String file) throws IOException, DataSetException + private JsonDataSet loadJsonDataSet(final String file, DBUnitConfiguration configuration) throws IOException, DataSetException { final InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(file); - return new JsonDataSet(inputStream); + return new JsonDataSet(inputStream, configuration); } private IDataSet loadYamlDataSet(final String file) throws IOException, diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java new file mode 100644 index 00000000..77b6388c --- /dev/null +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java @@ -0,0 +1,46 @@ +package org.jboss.arquillian.persistence.dbunit.dataset.json; + +import org.dbunit.dataset.datatype.DataType; +import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; +import org.dbunit.ext.oracle.Oracle10DataTypeFactory; + +public enum DatabaseDataType { + ORACLESTRING(JsonDataType.STRING, Oracle10DataTypeFactory.class, DataType.VARCHAR), + ORACLEBIGINTEGER(JsonDataType.BIGINTEGER, Oracle10DataTypeFactory.class, DataType.DECIMAL), + ORACLEINTEGER(JsonDataType.INTEGER, Oracle10DataTypeFactory.class, DataType.DECIMAL), + ORACLELONG(JsonDataType.LONG, Oracle10DataTypeFactory.class, DataType.DECIMAL), + ORACLETIMESTAMP(JsonDataType.TIMESTAMP, Oracle10DataTypeFactory.class, DataType.TIMESTAMP), + HSQLSTRING(JsonDataType.STRING, HsqldbDataTypeFactory.class, DataType.VARCHAR), + HSQLBIGINTEGER(JsonDataType.BIGINTEGER, HsqldbDataTypeFactory.class, DataType.BIGINT), + HSQLINTEGER(JsonDataType.INTEGER, HsqldbDataTypeFactory.class, DataType.BIGINT), + HSQLLONG(JsonDataType.LONG, HsqldbDataTypeFactory.class, DataType.BIGINT), + HSQLTIMESTAMP(JsonDataType.TIMESTAMP, HsqldbDataTypeFactory.class, DataType.TIMESTAMP); + + private JsonDataType jsonDataType; + + private Class databaseFactoryClazz; + + private DataType dataType; + + private DatabaseDataType(JsonDataType jsonDataType, Class databaseFactoryClazz, DataType dataType) + { + this.jsonDataType = jsonDataType; + this.databaseFactoryClazz = databaseFactoryClazz; + this.dataType = dataType; + } + + public JsonDataType getJsonDataType() + { + return jsonDataType; + } + + public DataType getDataType() + { + return dataType; + } + + public Class getDatabaseFactoryClass() + { + return databaseFactoryClazz; + } +} diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSet.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSet.java index de4b311b..db77d859 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSet.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSet.java @@ -25,6 +25,7 @@ import org.dbunit.dataset.CachedDataSet; import org.dbunit.dataset.DataSetException; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; /** * DBUnit data set produced from JSON format. @@ -75,14 +76,14 @@ public JsonDataSet(JsonDataSetProducer producer, boolean caseSensitiveTableNames super(producer, caseSensitiveTableNames); } - public JsonDataSet(File file, boolean caseSensitiveTableNames) throws DataSetException, FileNotFoundException + public JsonDataSet(File file, DBUnitConfiguration configuration, boolean caseSensitiveTableNames) throws DataSetException, FileNotFoundException { - this(new FileInputStream(file), caseSensitiveTableNames); + this(new FileInputStream(file), configuration, caseSensitiveTableNames); } - public JsonDataSet(File file) throws IOException, DataSetException + public JsonDataSet(File file, DBUnitConfiguration configuration) throws IOException, DataSetException { - this(new FileInputStream(file), false); + this(new FileInputStream(file), configuration, false); } public JsonDataSet(JsonDataSetProducer producer) throws DataSetException @@ -90,14 +91,14 @@ public JsonDataSet(JsonDataSetProducer producer) throws DataSetException this(producer, false); } - public JsonDataSet(InputStream inputStream) throws DataSetException + public JsonDataSet(InputStream inputStream, DBUnitConfiguration configuration) throws DataSetException { - this(inputStream, false); + this(inputStream, configuration, false); } - public JsonDataSet(InputStream inputStream, boolean caseSensitiveTableNames) throws DataSetException + public JsonDataSet(InputStream inputStream, DBUnitConfiguration configuration, boolean caseSensitiveTableNames) throws DataSetException { - this(new JsonDataSetProducer(inputStream), caseSensitiveTableNames); + this(new JsonDataSetProducer(inputStream, configuration), caseSensitiveTableNames); } } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetProducer.java index d7bdd315..07d28c82 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetProducer.java @@ -27,6 +27,7 @@ import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.dbunit.dataset.DataSetException; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; /** * Produces JSON data set from the given file. @@ -39,9 +40,9 @@ public class JsonDataSetProducer extends DataSetProducer { - public JsonDataSetProducer(InputStream input) + public JsonDataSetProducer(InputStream input, DBUnitConfiguration configuration) { - super(input); + super(input, configuration); } @Override diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java new file mode 100644 index 00000000..15aee000 --- /dev/null +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java @@ -0,0 +1,52 @@ +package org.jboss.arquillian.persistence.dbunit.dataset.json; + + +import org.dbunit.dataset.datatype.DataType; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.regex.Pattern; + +/** + * The regex pattern differentiates between the same data types reported by Jackson and the real data type to be applied + * for DBUnit so the comparison with the real data type read from the metadata of the database by DBUnit. Because we have + * no data type information available in JSON, we have to perform a best guess. For example, a normal String and a Timestamp + * are reported both as data type String and whould end up as a VARCHAR. The differentiation is done by an additional regex pattern + * which will detect the real datatypes. + */ +public enum JsonDataType { + STRING(String.class, "[^-|:]*", DataType.VARCHAR), + INTEGER(Integer.class, "\\d*", DataType.INTEGER), + LONG(Long.class, "\\d*", DataType.INTEGER), + BIGINTEGER(BigInteger.class, "\\d*", DataType.INTEGER), + UNKNOWN(ArrayList.class, ".*", DataType.UNKNOWN), // value == [null], we have no data type information available + TIMESTAMP(String.class, "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}[\\.\\d]*", DataType.TIMESTAMP); + + private Class clazz; + + private String regexPattern; + + private DataType defaultDataType; + + private JsonDataType(Class clazz, String regexPattern, DataType defaultDataType) + { + this.clazz = clazz; + this.regexPattern = regexPattern; + this.defaultDataType = defaultDataType; + } + + public String getRegexPattern() + { + return regexPattern; + } + + public Class getClazz() + { + return clazz; + } + + public DataType getDefaultDataType() + { + return defaultDataType; + } +} diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java index 2a87d9bc..effcc092 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverter.java @@ -19,75 +19,61 @@ import org.dbunit.dataset.datatype.DataType; +import org.dbunit.dataset.datatype.IDataTypeFactory; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.regex.Matcher; +import javax.enterprise.inject.Instance; +import javax.inject.Inject; import java.util.regex.Pattern; public class JsonDataTypeConverter { - public DataType convertJSonDataTypeToDBUnitDataType(Object value, Class clazz) - { - return JsonDataTypes.dataTypeForClass(value, clazz); - } + JsonDataTypeToDatabaseConverter jsonDataTypeToDatabaseConverter = new JsonDataTypeToDatabaseConverter(); - /** - * The regex pattern differentiates between the same data types reported by Jackson and the real data type to be applied - * for DBUnit so the comparison with the real data type read from the metadata of the database by DBUnit. Because we have - * no data type information available in JSON, we have to perform a best guess. For example, a normal String and a Timestamp - * are reported both as data type String and whould end up as a VARCHAR. The differentiation is done by an additional regex pattern - * which will detect the real datatypes. - */ - private static enum JsonDataTypes { - STRING(String.class, DataType.VARCHAR, "[^-|:]*"), - INTEGER(Integer.class, DataType.DECIMAL, "\\d*"), - LONG(Long.class,DataType.DECIMAL, "\\d*"), - BIGINTEGER(BigInteger.class, DataType.DECIMAL, "\\d*"), - UNKNOWN(ArrayList.class, DataType.UNKNOWN, ".*"), // value == [null], we have no data type information available - TIMESTAMP(String.class, DataType.TIMESTAMP, "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}[\\.\\d]*"); + @Inject + DBUnitConfiguration configuration; - private Class clazz; - - private DataType dataType; + public DataType convertJSonDataTypeToDBUnitDataType(Object value, Class clazz) + { + DataType dataType = DataType.UNKNOWN; - private String regexPattern; + JsonDataType jsonDataType = dataTypeForClass(value, clazz); - private JsonDataTypes(Class clazz, DataType dataType, String regexPattern) + if (jsonDataType != JsonDataType.UNKNOWN) { - this.clazz = clazz; - this.dataType = dataType; - this.regexPattern = regexPattern; + dataType = jsonDataTypeToDatabaseConverter.dataTpeForJsonDataType(jsonDataType, configuration.getDatatypeFactory()); } - public static DataType dataTypeForClass(Object value, Class clazz) + return dataType; + } + + public JsonDataType dataTypeForClass(Object value, Class clazz) + { + JsonDataType jsonDataType = JsonDataType.STRING; + + for (JsonDataType currentDataType : JsonDataType.values()) { - DataType dataType = DataType.VARCHAR; + boolean matches = match(value, currentDataType.getRegexPattern()); - for (JsonDataTypes currentDataType : JsonDataTypes.values()) + if (currentDataType.getClazz().equals(clazz) && matches) { - boolean matches = match(value, currentDataType.regexPattern); - - if (currentDataType.clazz.equals(clazz) && matches) - { - dataType = currentDataType.dataType; - } + jsonDataType = currentDataType; } - - return dataType; } - public static boolean match(Object value, String regexPattern) - { - boolean matches = false; + return jsonDataType; + } - if (null != regexPattern && null != value) - { - String stringValue = value.toString(); - matches = Pattern.matches(regexPattern, stringValue); - } + boolean match(Object value, String regexPattern) + { + boolean matches = false; - return matches; + if (null != regexPattern && null != value) + { + String stringValue = value.toString(); + matches = Pattern.matches(regexPattern, stringValue); } + + return matches; } } diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/DataSetComparatorTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/DataSetComparatorTest.java index 8d360852..b7dbddf3 100644 --- a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/DataSetComparatorTest.java +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/DataSetComparatorTest.java @@ -24,14 +24,26 @@ import java.util.Arrays; import org.dbunit.dataset.IDataSet; +import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; import org.jboss.arquillian.persistence.core.test.AssertionErrorCollector; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.jboss.arquillian.persistence.dbunit.data.descriptor.Format; import org.jboss.arquillian.persistence.dbunit.dataset.DataSetBuilder; +import org.junit.Before; import org.junit.Test; public class DataSetComparatorTest { + private DBUnitConfiguration configuration; + + @Before + public void setup() + { + configuration = new DBUnitConfiguration(); + configuration.setDatatypeFactory(new HsqldbDataTypeFactory()); + } + @Test public void should_map_columns_associated_with_particular_table() throws Exception { @@ -73,8 +85,8 @@ public void should_find_all_differences_between_datasets() throws Exception // given final AssertionErrorCollector errorCollector = new AssertionErrorCollector(); DataSetComparator dataSetComparator = new DataSetComparator(new String[] {}, new String[] {}); - IDataSet usersXml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml"); - IDataSet usersYaml = DataSetBuilder.builderFor(Format.YAML).build("datasets/users-modified.yml"); + IDataSet usersXml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml", configuration); + IDataSet usersYaml = DataSetBuilder.builderFor(Format.YAML).build("datasets/users-modified.yml", configuration); // when dataSetComparator.compare(usersXml, usersYaml, errorCollector); @@ -89,8 +101,8 @@ public void should_find_no_differences_between_identical_datasets() throws Excep // given final AssertionErrorCollector errorCollector = new AssertionErrorCollector(); DataSetComparator dataSetComparator = new DataSetComparator(new String[] {}, new String[] {}); - IDataSet usersXml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml"); - IDataSet usersYaml = DataSetBuilder.builderFor(Format.JSON).build("datasets/users.json"); + IDataSet usersXml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml", configuration); + IDataSet usersYaml = DataSetBuilder.builderFor(Format.JSON).build("datasets/users.json", configuration); // when dataSetComparator.compare(usersXml, usersYaml, errorCollector); @@ -105,8 +117,8 @@ public void should_find_no_differences_comparing_the_same_dataset() throws Excep // given final AssertionErrorCollector errorCollector = new AssertionErrorCollector(); DataSetComparator dataSetComparator = new DataSetComparator(new String[] {}, new String[] {}); - IDataSet usersXml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml"); - IDataSet usersYaml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml"); + IDataSet usersXml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml", configuration); + IDataSet usersYaml = DataSetBuilder.builderFor(Format.XML).build("datasets/users.xml", configuration); // when dataSetComparator.compare(usersXml, usersYaml, errorCollector); diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetTest.java index 775c3b55..720b49e1 100644 --- a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetTest.java +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataSetTest.java @@ -19,11 +19,14 @@ import java.io.InputStream; +import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; import org.jboss.arquillian.persistence.dbunit.DataSetAssert; import org.jboss.arquillian.persistence.dbunit.TableAssert; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.jboss.arquillian.persistence.dbunit.dataset.json.JsonDataSet; import org.jboss.arquillian.persistence.testutils.FileLoader; import org.junit.After; +import org.junit.Before; import org.junit.Test; public class JsonDataSetTest @@ -31,6 +34,15 @@ public class JsonDataSetTest private InputStream input; + private DBUnitConfiguration configuration; + + @Before + public void setup() + { + configuration = new DBUnitConfiguration(); + configuration.setDatatypeFactory(new HsqldbDataTypeFactory()); + } + @After public void closeStream() { @@ -44,7 +56,7 @@ public void should_load_table_from_json_file() throws Exception input = FileLoader.load("one-table.json"); // when - JsonDataSet jsonDataSet = new JsonDataSet(input); + JsonDataSet jsonDataSet = new JsonDataSet(input, configuration); // then DataSetAssert.assertThat(jsonDataSet).hasTables("useraccount"); @@ -57,7 +69,7 @@ public void should_load_all_columns_for_table_from_json_file() throws Exception input = FileLoader.load("one-table.json"); // when - JsonDataSet jsonDataSet = new JsonDataSet(input); + JsonDataSet jsonDataSet = new JsonDataSet(input, configuration); // then TableAssert.assertThat(jsonDataSet.getTable("useraccount")).hasColumns("id", "firstname", "lastname", "username", "password", "email"); @@ -70,7 +82,7 @@ public void should_load_all_rows_for_table_from_json_file() throws Exception input = FileLoader.load("one-table.json"); // when - JsonDataSet jsonDataSet = new JsonDataSet(input); + JsonDataSet jsonDataSet = new JsonDataSet(input, configuration); // then TableAssert.assertThat(jsonDataSet.getTable("useraccount")).hasRows(2); @@ -83,7 +95,7 @@ public void should_load_all_rows_with_content_for_table_from_json_file() throws input = FileLoader.load("one-table.json"); // when - JsonDataSet jsonDataSet = new JsonDataSet(input); + JsonDataSet jsonDataSet = new JsonDataSet(input, configuration); // then TableAssert.assertThat(jsonDataSet.getTable("useraccount")) @@ -98,7 +110,7 @@ public void should_load_two_tables_from_json_file() throws Exception input = FileLoader.load("tables.json"); // when - JsonDataSet jsonDataSet = new JsonDataSet(input); + JsonDataSet jsonDataSet = new JsonDataSet(input, configuration); // then DataSetAssert.assertThat(jsonDataSet).hasTables("useraccount", "testtable"); diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java index 347e0968..d82c39c5 100644 --- a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java @@ -2,6 +2,9 @@ import org.dbunit.dataset.datatype.DataType; +import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; +import org.dbunit.ext.oracle.Oracle10DataTypeFactory; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.junit.Before; import org.junit.Test; @@ -17,12 +20,15 @@ public class JsonDataTypeConverterTest { public void setup() { converter = new JsonDataTypeConverter(); + converter.configuration = new DBUnitConfiguration(); + converter.configuration.setDatatypeFactory(new HsqldbDataTypeFactory()); + converter.jsonDataTypeToDatabaseConverter = new JsonDataTypeToDatabaseConverter(); } @Test public void withInteger() { - assertEquals("DataType is not the expected one", DataType.DECIMAL, converter.convertJSonDataTypeToDBUnitDataType(Integer.valueOf(1), Integer.class)); + assertEquals("DataType is not the expected one", DataType.BIGINT, converter.convertJSonDataTypeToDBUnitDataType(Integer.valueOf(1), Integer.class)); } @Test diff --git a/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java b/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java index a2c9be08..d21eb652 100644 --- a/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java +++ b/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java @@ -101,7 +101,7 @@ private IDataSet createExpectedDataSet(AfterPersistenceTest afterPersistenceTest List dataSets = new ArrayList(descriptors.size()); for (DataSetResourceDescriptor dataSetDescriptor : descriptors) { - dataSets.add(dataSetDescriptor.getContent()); + dataSets.add(dataSetDescriptor.getContent(dbunitConfiguration.get())); } IDataSet expectedDataSet = DataSetUtils.mergeDataSets(dataSets); return expectedDataSet; From 1582833b315d60b392bb90c9062941a5223e40c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 17:11:15 +0100 Subject: [PATCH 08/15] Introduces a database data type mapper where the Json Data Types are mapped to the data types of the specific database. For this to happen, the DBUnitConfiguration is used to get the DataTypeFactory (database specific). --- .../dbunit/dataset/json/DataSetProducer.java | 15 +++++++++-- .../json/JsonDataTypeToDatabaseConverter.java | 25 +++++++++++++++++++ .../dataset/yaml/YamlDataSetProducer.java | 2 +- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeToDatabaseConverter.java diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java index d3e4e005..51c8740c 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; import org.dbunit.dataset.Column; import org.dbunit.dataset.DataSetException; @@ -33,9 +34,12 @@ import org.dbunit.dataset.stream.DefaultConsumer; import org.dbunit.dataset.stream.IDataSetConsumer; import org.dbunit.dataset.stream.IDataSetProducer; +import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.jboss.arquillian.persistence.dbunit.dataset.Row; import org.jboss.arquillian.persistence.dbunit.dataset.Table; +import javax.inject.Inject; + /** * Abstract DataSetProducer class with template method for producing data * set in the given format. @@ -46,15 +50,20 @@ public abstract class DataSetProducer implements IDataSetProducer { + private static final Logger log = Logger.getLogger(DataSetProducer.class.getName()); + + private JsonDataTypeConverter jsonDataTypeConverter = new JsonDataTypeConverter(); + private boolean caseSensitiveTableNames; private IDataSetConsumer consumer = new DefaultConsumer(); protected final InputStream input; - public DataSetProducer(InputStream input) + public DataSetProducer(InputStream input, DBUnitConfiguration configuration) { this.input = input; + jsonDataTypeConverter.configuration = configuration; } abstract Map>> loadDataSet() throws DataSetException; @@ -141,7 +150,9 @@ private Collection extractColumnsFromDatasetRow(Map row) Object value = currentEntry.getValue(); DataType dataType = null; - dataType = new JsonDataTypeConverter().convertJSonDataTypeToDBUnitDataType(value, value.getClass()); + dataType = jsonDataTypeConverter.convertJSonDataTypeToDBUnitDataType(value, value.getClass()); + + log.warning("Set DataType=" + dataType + " for column=" + columnName); columns.add(new Column(columnName, dataType)); } diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeToDatabaseConverter.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeToDatabaseConverter.java new file mode 100644 index 00000000..94a913e7 --- /dev/null +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeToDatabaseConverter.java @@ -0,0 +1,25 @@ +package org.jboss.arquillian.persistence.dbunit.dataset.json; + +import org.dbunit.dataset.datatype.DataType; +import org.dbunit.dataset.datatype.IDataTypeFactory; + +import java.util.logging.Logger; + +public class JsonDataTypeToDatabaseConverter { + + public DataType dataTpeForJsonDataType(JsonDataType jsonDataType, IDataTypeFactory factory) + { + DataType dataType = jsonDataType.getDefaultDataType(); + + for(DatabaseDataType currentDatabaseDataType : DatabaseDataType.values()) + { + if (currentDatabaseDataType.getDatabaseFactoryClass().equals(factory.getClass()) && + currentDatabaseDataType.getJsonDataType().equals(jsonDataType)) + { + dataType = currentDatabaseDataType.getDataType(); + } + } + + return dataType; + } +} diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java index 3d58f39d..2854c9af 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java @@ -179,7 +179,7 @@ private Collection extractColumnsFromDatasetRow(Map row) DataType dataType = null; if (value instanceof Integer) { - dataType = DataType.INTEGER; + dataType = DataType.BIGINT; } else { dataType = DataType.VARCHAR; } From c89e8b2d43c0b2575b2a626b942a5c1c7d4e1a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 20:44:47 +0100 Subject: [PATCH 09/15] Fixed datatype integer/string --- .../test/resources/datasets/clark-kent-without-nickname.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/int-tests/src/test/resources/datasets/clark-kent-without-nickname.json b/int-tests/src/test/resources/datasets/clark-kent-without-nickname.json index 5eba05b9..681dc719 100644 --- a/int-tests/src/test/resources/datasets/clark-kent-without-nickname.json +++ b/int-tests/src/test/resources/datasets/clark-kent-without-nickname.json @@ -2,7 +2,7 @@ "useraccount": [ { - "id": "2", + "id": 2, "firstname" : "Clark", "lastname" : "Kent", "username" : "ckent", From f86f59608bfcaefb7cd134550ac7a6da866be149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 20:46:03 +0100 Subject: [PATCH 10/15] Fixed datatype integer/string --- .../test/resources/datasets/clark-kent-without-nickname.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/int-tests-testng/src/test/resources/datasets/clark-kent-without-nickname.json b/int-tests-testng/src/test/resources/datasets/clark-kent-without-nickname.json index 5eba05b9..681dc719 100644 --- a/int-tests-testng/src/test/resources/datasets/clark-kent-without-nickname.json +++ b/int-tests-testng/src/test/resources/datasets/clark-kent-without-nickname.json @@ -2,7 +2,7 @@ "useraccount": [ { - "id": "2", + "id": 2, "firstname" : "Clark", "lastname" : "Kent", "username" : "ckent", From 616238e90fde7c6f0e7dd1fdb532745e740d3152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 21:38:22 +0100 Subject: [PATCH 11/15] Removed a logger. --- .../persistence/dbunit/dataset/json/DataSetProducer.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java index 51c8740c..ab90c5f1 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java @@ -49,9 +49,6 @@ */ public abstract class DataSetProducer implements IDataSetProducer { - - private static final Logger log = Logger.getLogger(DataSetProducer.class.getName()); - private JsonDataTypeConverter jsonDataTypeConverter = new JsonDataTypeConverter(); private boolean caseSensitiveTableNames; @@ -152,8 +149,6 @@ private Collection extractColumnsFromDatasetRow(Map row) dataType = jsonDataTypeConverter.convertJSonDataTypeToDBUnitDataType(value, value.getClass()); - log.warning("Set DataType=" + dataType + " for column=" + columnName); - columns.add(new Column(columnName, dataType)); } From 4474dc252a169bd850a1d58342686986a5647794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sat, 1 Dec 2012 21:49:21 +0100 Subject: [PATCH 12/15] YAML DataType is always UNKOWN. --- .../dbunit/dataset/yaml/YamlDataSetProducer.java | 8 +------- .../testextension/data/DataContentVerifier.java | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java index 2854c9af..2bd2d53b 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/yaml/YamlDataSetProducer.java @@ -176,13 +176,7 @@ private Collection extractColumnsFromDatasetRow(Map row) for (Map.Entry currentEntry : row.entrySet()) { String columnName = currentEntry.getKey(); Object value = currentEntry.getValue(); - DataType dataType = null; - - if (value instanceof Integer) { - dataType = DataType.BIGINT; - } else { - dataType = DataType.VARCHAR; - } + DataType dataType = DataType.UNKNOWN; columns.add(new Column(columnName, dataType)); } diff --git a/int-tests-testng/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java b/int-tests-testng/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java index a2c9be08..d21eb652 100644 --- a/int-tests-testng/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java +++ b/int-tests-testng/src/test/java/org/jboss/arquillian/integration/persistence/testextension/data/DataContentVerifier.java @@ -101,7 +101,7 @@ private IDataSet createExpectedDataSet(AfterPersistenceTest afterPersistenceTest List dataSets = new ArrayList(descriptors.size()); for (DataSetResourceDescriptor dataSetDescriptor : descriptors) { - dataSets.add(dataSetDescriptor.getContent()); + dataSets.add(dataSetDescriptor.getContent(dbunitConfiguration.get())); } IDataSet expectedDataSet = DataSetUtils.mergeDataSets(dataSets); return expectedDataSet; From 33821f339d1a2d818de3f9117d4055da32bf08b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sun, 2 Dec 2012 08:38:47 +0100 Subject: [PATCH 13/15] Added datatypes Boolean and Double. --- .../dbunit/dataset/json/DatabaseDataType.java | 9 ++++----- .../persistence/dbunit/dataset/json/JsonDataType.java | 5 ++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java index 77b6388c..a463c60a 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java @@ -4,17 +4,16 @@ import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; import org.dbunit.ext.oracle.Oracle10DataTypeFactory; +/** + * Only define exceptions to the default value defined in JsonDataType. + */ public enum DatabaseDataType { - ORACLESTRING(JsonDataType.STRING, Oracle10DataTypeFactory.class, DataType.VARCHAR), ORACLEBIGINTEGER(JsonDataType.BIGINTEGER, Oracle10DataTypeFactory.class, DataType.DECIMAL), ORACLEINTEGER(JsonDataType.INTEGER, Oracle10DataTypeFactory.class, DataType.DECIMAL), ORACLELONG(JsonDataType.LONG, Oracle10DataTypeFactory.class, DataType.DECIMAL), - ORACLETIMESTAMP(JsonDataType.TIMESTAMP, Oracle10DataTypeFactory.class, DataType.TIMESTAMP), - HSQLSTRING(JsonDataType.STRING, HsqldbDataTypeFactory.class, DataType.VARCHAR), HSQLBIGINTEGER(JsonDataType.BIGINTEGER, HsqldbDataTypeFactory.class, DataType.BIGINT), HSQLINTEGER(JsonDataType.INTEGER, HsqldbDataTypeFactory.class, DataType.BIGINT), - HSQLLONG(JsonDataType.LONG, HsqldbDataTypeFactory.class, DataType.BIGINT), - HSQLTIMESTAMP(JsonDataType.TIMESTAMP, HsqldbDataTypeFactory.class, DataType.TIMESTAMP); + HSQLLONG(JsonDataType.LONG, HsqldbDataTypeFactory.class, DataType.BIGINT); private JsonDataType jsonDataType; diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java index 15aee000..61bad4e7 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataType.java @@ -12,13 +12,16 @@ * for DBUnit so the comparison with the real data type read from the metadata of the database by DBUnit. Because we have * no data type information available in JSON, we have to perform a best guess. For example, a normal String and a Timestamp * are reported both as data type String and whould end up as a VARCHAR. The differentiation is done by an additional regex pattern - * which will detect the real datatypes. + * which will detect the real datatypes. The Json data type mapping to java is documented here + * http://wiki.fasterxml.com/JacksonInFiveMinutes. */ public enum JsonDataType { STRING(String.class, "[^-|:]*", DataType.VARCHAR), INTEGER(Integer.class, "\\d*", DataType.INTEGER), LONG(Long.class, "\\d*", DataType.INTEGER), BIGINTEGER(BigInteger.class, "\\d*", DataType.INTEGER), + DOUBLE(Double.class, "\\d*\\.\\d*", DataType.DOUBLE), + BOOLEAN(Boolean.class, ".*", DataType.BOOLEAN), UNKNOWN(ArrayList.class, ".*", DataType.UNKNOWN), // value == [null], we have no data type information available TIMESTAMP(String.class, "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}[\\.\\d]*", DataType.TIMESTAMP); From b1a842aa2218da9d338c4438b32d98d2d33604a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Sun, 2 Dec 2012 13:56:44 +0100 Subject: [PATCH 14/15] Added the logic to override columns with a unknown data type ([null) ]but another column has the correct datatype. --- .../dbunit/dataset/json/DataSetProducer.java | 35 ++++++++++++++++++- .../json/JsonDataTypeConverterTest.java | 13 +++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java index ab90c5f1..f711e8a9 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DataSetProducer.java @@ -134,11 +134,44 @@ private Collection extractColumns(List> rows) final Set columns = new HashSet(); for (Map row : rows) { - columns.addAll(extractColumnsFromDatasetRow(row)); + addAndOverrideUnknownDataTypeColumns(columns, extractColumnsFromDatasetRow(row)); } + return columns; } + private void addAndOverrideUnknownDataTypeColumns(Set tableColumns, Collection columnsToAdd) + { + for (Column currentColumnToAdd : columnsToAdd) + { + Column existingColumn = columnForColumnName(tableColumns, currentColumnToAdd.getColumnName()); + + if (null == existingColumn) + { + tableColumns.add(currentColumnToAdd); + } else if (existingColumn.getDataType().equals(DataType.UNKNOWN) && !currentColumnToAdd.getDataType().equals(DataType.UNKNOWN)) + { + tableColumns.remove(existingColumn); + tableColumns.add(currentColumnToAdd); + } + } + } + + private Column columnForColumnName(Set columns, String columnName) + { + Column column = null; + + for (Column currentColumn : columns) + { + if (currentColumn.getColumnName().equals(columnName)) + { + column = currentColumn; + } + } + + return column; + } + private Collection extractColumnsFromDatasetRow(Map row) { final Set columns = new HashSet(); diff --git a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java index d82c39c5..ba45d2ef 100644 --- a/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java +++ b/impl/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/json/JsonDataTypeConverterTest.java @@ -31,11 +31,24 @@ public void withInteger() assertEquals("DataType is not the expected one", DataType.BIGINT, converter.convertJSonDataTypeToDBUnitDataType(Integer.valueOf(1), Integer.class)); } + @Test + public void withDouble() + { + assertEquals("DataType is not the expected one", DataType.DOUBLE, converter.convertJSonDataTypeToDBUnitDataType(Double.valueOf(12.345345), Double.class)); + } + + @Test + public void withBoolean() + { + assertEquals("DataType is not the expected one", DataType.BOOLEAN, converter.convertJSonDataTypeToDBUnitDataType("true", Boolean.class)); + } + @Test public void withString() { assertEquals("DataType is not the expected one", DataType.VARCHAR, converter.convertJSonDataTypeToDBUnitDataType("Good morning", String.class)); } + @Test public void withNull() { From c70c1bc2f76093d5ac03ee30f974ac379e07ca81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyrill=20Ru=CC=88ttimann?= Date: Mon, 3 Dec 2012 22:37:36 +0100 Subject: [PATCH 15/15] DatabaseDataType fix for the oracle database double datatype. --- .../persistence/dbunit/dataset/json/DatabaseDataType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java index a463c60a..58ae360f 100644 --- a/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java +++ b/impl/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/json/DatabaseDataType.java @@ -11,6 +11,7 @@ public enum DatabaseDataType { ORACLEBIGINTEGER(JsonDataType.BIGINTEGER, Oracle10DataTypeFactory.class, DataType.DECIMAL), ORACLEINTEGER(JsonDataType.INTEGER, Oracle10DataTypeFactory.class, DataType.DECIMAL), ORACLELONG(JsonDataType.LONG, Oracle10DataTypeFactory.class, DataType.DECIMAL), + ORACLEDOUBLE(JsonDataType.DOUBLE, Oracle10DataTypeFactory.class, DataType.DECIMAL), HSQLBIGINTEGER(JsonDataType.BIGINTEGER, HsqldbDataTypeFactory.class, DataType.BIGINT), HSQLINTEGER(JsonDataType.INTEGER, HsqldbDataTypeFactory.class, DataType.BIGINT), HSQLLONG(JsonDataType.LONG, HsqldbDataTypeFactory.class, DataType.BIGINT);