From c683594f59030e5515b95ff7d8d0b9fa66eaac42 Mon Sep 17 00:00:00 2001 From: Sebb Date: Fri, 14 Jun 2019 17:21:33 +0100 Subject: [PATCH] CSV-242 CSVFormat equals() and hashCode() don't use all fields Fix hashCode() --- src/changes/changes.xml | 363 +++++++++--------- .../org/apache/commons/csv/CSVFormat.java | 6 + .../org/apache/commons/csv/CSVFormatTest.java | 5 +- 3 files changed, 192 insertions(+), 182 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6fa07c81..38acf73b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -1,181 +1,182 @@ - - - - - - - - Apache Commons CSV Release Notes - - - - CSVFormat#valiadte() does not account for allowDuplicateHeaderNames #43. - - - Add predefined CSVFormats for printing MongoDB CSV and TSV. - Fix escape character for POSTGRESQL_TEXT and POSTGRESQL_CSV formats. - Site link "Source Repository" does not work. - Add support for java.sql.Clob. - Update to Java 8. - Escape quotes in CLOBs #39. - Cannot get headers in column order from CSVRecord. - Update tests from H2 1.4.198 to 1.4.199. - - - Add more documentation to CSVPrinter. - Add autoFlush option for CsvPrinter. PR #24. - The behavior of quote char using is not similar as Excel does when the first string contains CJK char(s). - Don't quote cells just because they have UTF-8 encoded characters. - Add API org.apache.commons.csv.CSVFormat.withSystemRecordSeparator(). - Inconsistency between Javadoc of CSVFormat DEFAULT EXCEL. - Create CSVFormat.ORACLE preset. - Some multi-iterator parsing peek sequences incorrectly consume elements. - Parse method should avoid creating a redundant BufferedReader. - Add predefined CSVFormats for printing MongoDB CSV and TSV. - - - withNullString value is printed without quotes when QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17. - Fix outdated comments about FileReader in CSVParser #13 - Fix incorrect method name 'withFirstRowAsHeader' in user guide. - Negative numeric values in the first column are always quoted in minimal mode. - Update platform requirement from Java 6 to 7. - Do not use RuntimeException in CSVParser.iterator().new Iterator() {...}.getNextRecord() - CSVParser: Add factory method accepting InputStream. - Add convenience API CSVFormat.print(File, Charset) - Add convenience API CSVFormat.print(Path, Charset) - Add convenience API CSVParser.parse(Path, Charset, CSVFormat) - Add convenience API CSVFormat#printer() to print to System.out - Provide a CSV Format for printing PostgreSQL CSV and Text formats. - Adding a placeholder in the Lexer and CSV parser to store the end-of-line string. - - - Make CSVPrinter.print(Object) GC-free. - Allow some printing operations directly from CSVFormat. - Drop ferc.gov tests. - - - Add shortcut method for using first record as header to CSVFormat - Add withHeader(Class<? extends Enum>) to CSVFormat - Comment line hides next record; update Javadoc to make behavior clear - CSVPrinter doesn't skip creation of header record if skipHeaderRecord is set to true - Add IgnoreCase option for accessing header names - The null string should be case-sensitive when reading records - CSVFormat.nullString should not be escaped - CSVFormat.MYSQL nullString should be "\N" - Fix Javadoc to say CSVFormat with() methods return a new CSVFormat - Support for ignoring trailing delimiter. - Support trimming leading and trailing blanks. - Create default formats for Informix UNLOAD and UNLOAD CSV. - - - CSVFormat.with* methods clear the header comments - Incorrect Javadoc on QuoteMode.NONE - Add enum CSVFormat.Predefined that contains the default CSVFormat values. - - - QuoteMode.NON_NUMERIC doesn't work with CSVPrinter.printRecords(ResultSet) - CSVFormat#withHeader doesn't work well with #printComment, add withHeaderComments(String...) - CSVFormat.EXCEL should ignore empty header names - Incorrect Javadoc referencing org.apache.commons.csv.CSVFormat withQuote() - Improve toString() implementation of CSVRecord - Unified parameter validation - Add CSVFormat#with 0-arg methods matching boolean arg methods - Save positions of records to enable random access - CSVPrinter.printRecord(ResultSet) with metadata - - - No longer works with Java 6 - NullPointerException when empty header string and and null string of "" - Validate format parameters in constructor - IllegalArgumentException thrown when the header contains duplicate names when the column names are empty. - CSVFormat#withHeader doesn't work with CSVPrinter - CSVFormat is missing a print(...) method - CSVRecord.toMap() throws NPE on formats with no - headers. - Check whether ISE/IAE are being used appropriately - CSVFormat constructor should reject a header array with duplicate - entries - - HeaderMap is inconsistent when it is parsed from an input with - duplicate columns names - - CSVRecord.toMap() fails if row length shorter than header length - - CSVFormat.format allways append null - Add Map conversion API to CSVRecord - CSVParser: getHeaderMap throws NPE - Lots of possible changes - Use Character instead of char for char fields except delimiter - - Revert Builder implementation in CSVFormat - CSVRecord does not verify that the length of the header mapping - matches the number of values - - Allow the handling of NULL values - Use the Builder pattern for CSVFormat - Clarify comment handling - CSVParser.nextValue() seems pointless - Allow the String value for null to be customized for the CSV - printer - - Not possible to create a CSVFormat from scratch - Keep track of record number - Lexer should only use char fields - Need a way to extract parsed headers, e.g. for use in formatting - output - - Header support - Confusing semantic of the ignore leading/trailing spaces parameters - - Add convenience methods to CSVLexer - Is CharBuffer really needed, now that StringBuilder is available? - - Replace while(true)-loop in CSVParser.getRecord with do-while-loop - - CSVFormat describes itself as immutable, but it is not - in - particular it is not thread-safe - - Endless loops in CSV parser - NullPointerException in CSVPrinter.print()/println() - CSVPrinter overhaul - Excel strategy uses wrong separator - CSVStrategy has modifiable public static variables - - Predefined format for MYSQL - Reduce visibility of methods in internal classes - ExtendedBufferedReader does too much - Decide whether to keep the csv.writer subpackage - - - - + + + + + + + + Apache Commons CSV Release Notes + + + + CSVFormat equals() and hash() don't use all fields + CSVFormat#valiadte() does not account for allowDuplicateHeaderNames #43. + + + Add predefined CSVFormats for printing MongoDB CSV and TSV. + Fix escape character for POSTGRESQL_TEXT and POSTGRESQL_CSV formats. + Site link "Source Repository" does not work. + Add support for java.sql.Clob. + Update to Java 8. + Escape quotes in CLOBs #39. + Cannot get headers in column order from CSVRecord. + Update tests from H2 1.4.198 to 1.4.199. + + + Add more documentation to CSVPrinter. + Add autoFlush option for CsvPrinter. PR #24. + The behavior of quote char using is not similar as Excel does when the first string contains CJK char(s). + Don't quote cells just because they have UTF-8 encoded characters. + Add API org.apache.commons.csv.CSVFormat.withSystemRecordSeparator(). + Inconsistency between Javadoc of CSVFormat DEFAULT EXCEL. + Create CSVFormat.ORACLE preset. + Some multi-iterator parsing peek sequences incorrectly consume elements. + Parse method should avoid creating a redundant BufferedReader. + Add predefined CSVFormats for printing MongoDB CSV and TSV. + + + withNullString value is printed without quotes when QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17. + Fix outdated comments about FileReader in CSVParser #13 + Fix incorrect method name 'withFirstRowAsHeader' in user guide. + Negative numeric values in the first column are always quoted in minimal mode. + Update platform requirement from Java 6 to 7. + Do not use RuntimeException in CSVParser.iterator().new Iterator() {...}.getNextRecord() + CSVParser: Add factory method accepting InputStream. + Add convenience API CSVFormat.print(File, Charset) + Add convenience API CSVFormat.print(Path, Charset) + Add convenience API CSVParser.parse(Path, Charset, CSVFormat) + Add convenience API CSVFormat#printer() to print to System.out + Provide a CSV Format for printing PostgreSQL CSV and Text formats. + Adding a placeholder in the Lexer and CSV parser to store the end-of-line string. + + + Make CSVPrinter.print(Object) GC-free. + Allow some printing operations directly from CSVFormat. + Drop ferc.gov tests. + + + Add shortcut method for using first record as header to CSVFormat + Add withHeader(Class<? extends Enum>) to CSVFormat + Comment line hides next record; update Javadoc to make behavior clear + CSVPrinter doesn't skip creation of header record if skipHeaderRecord is set to true + Add IgnoreCase option for accessing header names + The null string should be case-sensitive when reading records + CSVFormat.nullString should not be escaped + CSVFormat.MYSQL nullString should be "\N" + Fix Javadoc to say CSVFormat with() methods return a new CSVFormat + Support for ignoring trailing delimiter. + Support trimming leading and trailing blanks. + Create default formats for Informix UNLOAD and UNLOAD CSV. + + + CSVFormat.with* methods clear the header comments + Incorrect Javadoc on QuoteMode.NONE + Add enum CSVFormat.Predefined that contains the default CSVFormat values. + + + QuoteMode.NON_NUMERIC doesn't work with CSVPrinter.printRecords(ResultSet) + CSVFormat#withHeader doesn't work well with #printComment, add withHeaderComments(String...) + CSVFormat.EXCEL should ignore empty header names + Incorrect Javadoc referencing org.apache.commons.csv.CSVFormat withQuote() + Improve toString() implementation of CSVRecord + Unified parameter validation + Add CSVFormat#with 0-arg methods matching boolean arg methods + Save positions of records to enable random access + CSVPrinter.printRecord(ResultSet) with metadata + + + No longer works with Java 6 + NullPointerException when empty header string and and null string of "" + Validate format parameters in constructor + IllegalArgumentException thrown when the header contains duplicate names when the column names are empty. + CSVFormat#withHeader doesn't work with CSVPrinter + CSVFormat is missing a print(...) method + CSVRecord.toMap() throws NPE on formats with no + headers. + Check whether ISE/IAE are being used appropriately + CSVFormat constructor should reject a header array with duplicate + entries + + HeaderMap is inconsistent when it is parsed from an input with + duplicate columns names + + CSVRecord.toMap() fails if row length shorter than header length + + CSVFormat.format allways append null + Add Map conversion API to CSVRecord + CSVParser: getHeaderMap throws NPE + Lots of possible changes + Use Character instead of char for char fields except delimiter + + Revert Builder implementation in CSVFormat + CSVRecord does not verify that the length of the header mapping + matches the number of values + + Allow the handling of NULL values + Use the Builder pattern for CSVFormat + Clarify comment handling + CSVParser.nextValue() seems pointless + Allow the String value for null to be customized for the CSV + printer + + Not possible to create a CSVFormat from scratch + Keep track of record number + Lexer should only use char fields + Need a way to extract parsed headers, e.g. for use in formatting + output + + Header support + Confusing semantic of the ignore leading/trailing spaces parameters + + Add convenience methods to CSVLexer + Is CharBuffer really needed, now that StringBuilder is available? + + Replace while(true)-loop in CSVParser.getRecord with do-while-loop + + CSVFormat describes itself as immutable, but it is not - in + particular it is not thread-safe + + Endless loops in CSV parser + NullPointerException in CSVPrinter.print()/println() + CSVPrinter overhaul + Excel strategy uses wrong separator + CSVStrategy has modifiable public static variables + + Predefined format for MYSQL + Reduce visibility of methods in internal classes + ExtendedBufferedReader does too much + Decide whether to keep the csv.writer subpackage + + + + diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 05317862..122f9068 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -1089,8 +1089,14 @@ public final class CSVFormat implements Serializable { result = prime * result + (ignoreHeaderCase ? 1231 : 1237); result = prime * result + (ignoreEmptyLines ? 1231 : 1237); result = prime * result + (skipHeaderRecord ? 1231 : 1237); + result = prime * result + (allowDuplicateHeaderNames ? 1231 : 1237); + result = prime * result + (trim ? 1231 : 1237); + result = prime * result + (autoFlush ? 1231 : 1237); + result = prime * result + (trailingDelimiter ? 1231 : 1237); + result = prime * result + (allowMissingColumnNames ? 1231 : 1237); result = prime * result + ((recordSeparator == null) ? 0 : recordSeparator.hashCode()); result = prime * result + Arrays.hashCode(header); + result = prime * result + Arrays.hashCode(headerComments); return result; } diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index 1d5cf563..10d48dd1 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -1112,7 +1112,10 @@ public class CSVFormatTest { private void assertNotEquals(String name, String type, Object left, Object right) { if (left.equals(right) || right.equals(left)) { - System.out.println("Should not be equal for " + name + "(" + type + ")"); + fail("Objects must not compare equal for " + name + "(" + type + ")"); + } + if (left.hashCode() == right.hashCode()) { + fail("Hash code not be equal for " + name + "(" + type + ")"); } }