You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2015/10/14 21:48:29 UTC

svn commit: r1708685 - in /commons/proper/csv/trunk/src: changes/changes.xml main/java/org/apache/commons/csv/CSVFormat.java main/java/org/apache/commons/csv/CSVParser.java test/java/org/apache/commons/csv/CSVParserTest.java

Author: ggregory
Date: Wed Oct 14 19:48:29 2015
New Revision: 1708685

URL: http://svn.apache.org/viewvc?rev=1708685&view=rev
Log:
[CSV-159] Add IgnoreCase option for accessing header names

Modified:
    commons/proper/csv/trunk/src/changes/changes.xml
    commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java
    commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java
    commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java

Modified: commons/proper/csv/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/changes/changes.xml?rev=1708685&r1=1708684&r2=1708685&view=diff
==============================================================================
--- commons/proper/csv/trunk/src/changes/changes.xml (original)
+++ commons/proper/csv/trunk/src/changes/changes.xml Wed Oct 14 19:48:29 2015
@@ -40,6 +40,7 @@
   <body>
     <release version="1.3" date="2015-MM-DD" description="Feature and bug fix release">
       <action issue="CSV-153" type="update" dev="britter" due-to="Wren">CSVPrinter doesn't skip creation of header record if skipHeaderRecord is set to true</action>
+      <action issue="CSV-159" type="add" dev="ggregory" due-to="Yamil Medina">Add IgnoreCase option for accessing header names</action>
     </release>
     <release version="1.2" date="2015-08-24" description="Feature and bug fix release">
       <action issue="CSV-145" type="fix" dev="ggregory" due-to="Frank Ulbricht">CSVFormat.with* methods clear the header comments</action>

Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java
URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java?rev=1708685&r1=1708684&r2=1708685&view=diff
==============================================================================
--- commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java (original)
+++ commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java Wed Oct 14 19:48:29 2015
@@ -210,6 +210,7 @@ public final class CSVFormat implements
     private final String[] header; // array of header column names
     private final String[] headerComments; // array of header comment lines
     private final boolean skipHeaderRecord;
+    private final boolean ignoreHeaderCase; // should ignore header names case
 
     /**
      * Standard comma separated format, as for {@link #RFC4180} but allowing empty lines.
@@ -226,7 +227,7 @@ public final class CSVFormat implements
      * @see Predefined#Default
      */
     public static final CSVFormat DEFAULT = new CSVFormat(COMMA, DOUBLE_QUOTE_CHAR, null, null, null, false, true,
-            CRLF, null, null, null, false, false);
+            CRLF, null, null, null, false, false, false);
 
     /**
      * Comma separated format as defined by <a href="http://tools.ietf.org/html/rfc4180">RFC 4180</a>.
@@ -361,7 +362,7 @@ public final class CSVFormat implements
      * @see #TDF
      */
     public static CSVFormat newFormat(final char delimiter) {
-        return new CSVFormat(delimiter, null, null, null, null, false, false, null, null, null, null, false, false);
+        return new CSVFormat(delimiter, null, null, null, null, false, false, null, null, null, null, false, false, false);
     }
 
     /**
@@ -405,6 +406,8 @@ public final class CSVFormat implements
      *            TODO
      * @param allowMissingColumnNames
      *            TODO
+     * @param ignoreHeaderCase
+     *            TODO
      * @throws IllegalArgumentException
      *             if the delimiter is a line break character
      */
@@ -412,7 +415,7 @@ public final class CSVFormat implements
             final Character commentStart, final Character escape, final boolean ignoreSurroundingSpaces,
             final boolean ignoreEmptyLines, final String recordSeparator, final String nullString,
             final Object[] headerComments, final String[] header, final boolean skipHeaderRecord,
-            final boolean allowMissingColumnNames) {
+            final boolean allowMissingColumnNames, final boolean ignoreHeaderCase) {
         this.delimiter = delimiter;
         this.quoteCharacter = quoteChar;
         this.quoteMode = quoteMode;
@@ -426,6 +429,7 @@ public final class CSVFormat implements
         this.headerComments = toStringArray(headerComments);
         this.header = header == null ? null : header.clone();
         this.skipHeaderRecord = skipHeaderRecord;
+        this.ignoreHeaderCase = ignoreHeaderCase;
         validate();
     }
 
@@ -603,6 +607,15 @@ public final class CSVFormat implements
     }
 
     /**
+     * Specifies whether header names will be accessed ignoring case.
+     *
+     * @return {@code true} if header names cases are ignored, {@code false} if they are case sensitive.
+     */
+    public boolean getIgnoreHeaderCase() {
+        return ignoreHeaderCase;
+    }
+
+    /**
      * Gets the String to convert to and from {@code null}.
      * <ul>
      * <li>
@@ -666,6 +679,7 @@ public final class CSVFormat implements
         result = prime * result + ((escapeCharacter == null) ? 0 : escapeCharacter.hashCode());
         result = prime * result + ((nullString == null) ? 0 : nullString.hashCode());
         result = prime * result + (ignoreSurroundingSpaces ? 1231 : 1237);
+        result = prime * result + (ignoreHeaderCase ? 1231 : 1237);
         result = prime * result + (ignoreEmptyLines ? 1231 : 1237);
         result = prime * result + (skipHeaderRecord ? 1231 : 1237);
         result = prime * result + ((recordSeparator == null) ? 0 : recordSeparator.hashCode());
@@ -775,6 +789,9 @@ public final class CSVFormat implements
         if (getIgnoreSurroundingSpaces()) {
             sb.append(" SurroundingSpaces:ignored");
         }
+        if (getIgnoreHeaderCase()) {
+            sb.append(" IgnoreHeaderCase:ignored");
+        }
         sb.append(" SkipHeaderRecord:").append(skipHeaderRecord);
         if (headerComments != null) {
             sb.append(' ');
@@ -870,7 +887,7 @@ public final class CSVFormat implements
         }
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -888,7 +905,7 @@ public final class CSVFormat implements
         }
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -919,7 +936,7 @@ public final class CSVFormat implements
         }
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces,
                 ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
-                allowMissingColumnNames);
+                allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -947,7 +964,7 @@ public final class CSVFormat implements
     public CSVFormat withHeader(final String... header) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1015,7 +1032,7 @@ public final class CSVFormat implements
         }
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, labels,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1036,7 +1053,7 @@ public final class CSVFormat implements
     public CSVFormat withHeaderComments(final Object... headerComments) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1061,7 +1078,7 @@ public final class CSVFormat implements
     public CSVFormat withAllowMissingColumnNames(final boolean allowMissingColumnNames) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1086,7 +1103,7 @@ public final class CSVFormat implements
     public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1111,7 +1128,32 @@ public final class CSVFormat implements
     public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
+    }
+
+    /**
+     * Sets the header ignore case behavior to {@code true}.
+     *
+     * @return A new CSVFormat that will ignore case header name.
+     * @see #withIgnoreHeaderCase(boolean)
+     * @since ?
+     */
+    public CSVFormat withIgnoreHeaderCase() {
+        return this.withIgnoreHeaderCase(true);
+    }
+
+    /**
+     * Sets if header names should be accessed ignoring case.
+     *
+     * @param ignoreHeaderCase
+     *            the case mapping behavior, {@code true} to access name/values, {@code false} to leave the
+     *            mapping as is.
+     * @return A new CSVFormat that will ignore case header name if specified as {@code true}
+     */
+    public CSVFormat withIgnoreHeaderCase(final boolean ignoreHeaderCase) {
+        return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
+                ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1132,7 +1174,7 @@ public final class CSVFormat implements
     public CSVFormat withNullString(final String nullString) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1163,7 +1205,7 @@ public final class CSVFormat implements
         }
         return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces,
                 ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
-                allowMissingColumnNames);
+                allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1177,7 +1219,7 @@ public final class CSVFormat implements
     public CSVFormat withQuoteMode(final QuoteMode quoteModePolicy) {
         return new CSVFormat(delimiter, quoteCharacter, quoteModePolicy, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1215,7 +1257,7 @@ public final class CSVFormat implements
     public CSVFormat withRecordSeparator(final String recordSeparator) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 
     /**
@@ -1242,6 +1284,6 @@ public final class CSVFormat implements
     public CSVFormat withSkipHeaderRecord(final boolean skipHeaderRecord) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
                 ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
-                skipHeaderRecord, allowMissingColumnNames);
+                skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
     }
 }

Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java
URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java?rev=1708685&r1=1708684&r2=1708685&view=diff
==============================================================================
--- commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java (original)
+++ commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java Wed Oct 14 19:48:29 2015
@@ -33,6 +33,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.TreeMap;
 
 import static org.apache.commons.csv.Token.Type.*;
 
@@ -378,7 +379,9 @@ public final class CSVParser implements
         Map<String, Integer> hdrMap = null;
         final String[] formatHeader = this.format.getHeader();
         if (formatHeader != null) {
-            hdrMap = new LinkedHashMap<String, Integer>();
+            hdrMap = this.format.getIgnoreHeaderCase()
+                    ? new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER)
+                    : new LinkedHashMap<String, Integer>();
 
             String[] headerRecord = null;
             if (formatHeader.length == 0) {

Modified: commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java
URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java?rev=1708685&r1=1708684&r2=1708685&view=diff
==============================================================================
--- commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java (original)
+++ commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java Wed Oct 14 19:48:29 2015
@@ -973,4 +973,15 @@ public class CSVParserTest {
 
         parser.close();
     }
+
+    @Test
+    public void testIgnoreCaseHeaderMapping() throws Exception {
+        final Reader in = new StringReader("1,2,3");
+        final Iterator<CSVRecord> records = CSVFormat.DEFAULT.withHeader("One", "TWO", "three").withIgnoreHeaderCase()
+                .parse(in).iterator();
+        final CSVRecord record = records.next();
+        assertEquals("1", record.get("one"));
+        assertEquals("2", record.get("two"));
+        assertEquals("3", record.get("THREE"));
+    }
 }