Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 59 additions & 17 deletions src/main/java/org/apache/commons/csv/CSVFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ public CSVFormat getFormat() {
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.
Expand All @@ -226,7 +227,7 @@ public CSVFormat getFormat() {
* @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>.
Expand Down Expand Up @@ -361,7 +362,7 @@ private static boolean isLineBreak(final Character c) {
* @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);
}

/**
Expand Down Expand Up @@ -405,14 +406,16 @@ public static CSVFormat valueOf(final String format) {
* TODO
* @param allowMissingColumnNames
* TODO
* @param ignoreHeaderCase
* TODO
* @throws IllegalArgumentException
* if the delimiter is a line break character
*/
private CSVFormat(final char delimiter, final Character quoteChar, final QuoteMode quoteMode,
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;
Expand All @@ -426,6 +429,7 @@ private CSVFormat(final char delimiter, final Character quoteChar, final QuoteMo
this.headerComments = toStringArray(headerComments);
this.header = header == null ? null : header.clone();
this.skipHeaderRecord = skipHeaderRecord;
this.ignoreHeaderCase = ignoreHeaderCase;
validate();
}

Expand Down Expand Up @@ -602,6 +606,15 @@ public boolean getIgnoreSurroundingSpaces() {
return ignoreSurroundingSpaces;
}

/**
* 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>
Expand Down Expand Up @@ -666,6 +679,7 @@ public int hashCode() {
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());
Expand Down Expand Up @@ -775,6 +789,9 @@ public String toString() {
if (getIgnoreSurroundingSpaces()) {
sb.append(" SurroundingSpaces:ignored");
}
if (getIgnoreHeaderCase()) {
sb.append(" IgnoreHeaderCase:ignored");
}
sb.append(" SkipHeaderRecord:").append(skipHeaderRecord);
if (headerComments != null) {
sb.append(' ');
Expand Down Expand Up @@ -870,7 +887,7 @@ public CSVFormat withCommentMarker(final Character commentMarker) {
}
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
skipHeaderRecord, allowMissingColumnNames);
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
}

/**
Expand All @@ -888,7 +905,7 @@ public CSVFormat withDelimiter(final char delimiter) {
}
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
skipHeaderRecord, allowMissingColumnNames);
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
}

/**
Expand Down Expand Up @@ -919,7 +936,7 @@ public CSVFormat withEscape(final Character escape) {
}
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces,
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
allowMissingColumnNames);
allowMissingColumnNames, ignoreHeaderCase);
}

/**
Expand Down Expand Up @@ -947,7 +964,7 @@ public CSVFormat withEscape(final Character escape) {
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);
}

/**
Expand Down Expand Up @@ -1015,7 +1032,7 @@ public CSVFormat withHeader(final ResultSetMetaData metaData) throws SQLExceptio
}
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, labels,
skipHeaderRecord, allowMissingColumnNames);
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase);
}

/**
Expand All @@ -1036,7 +1053,7 @@ public CSVFormat withHeader(final ResultSetMetaData metaData) throws SQLExceptio
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);
}

/**
Expand All @@ -1061,7 +1078,7 @@ public CSVFormat withAllowMissingColumnNames() {
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);
}

/**
Expand All @@ -1086,7 +1103,7 @@ public CSVFormat withIgnoreEmptyLines() {
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);
}

/**
Expand All @@ -1111,7 +1128,32 @@ public CSVFormat withIgnoreSurroundingSpaces() {
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);
}

/**
Expand All @@ -1132,7 +1174,7 @@ public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpac
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);
}

/**
Expand Down Expand Up @@ -1163,7 +1205,7 @@ public CSVFormat withQuote(final Character quoteChar) {
}
return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces,
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
allowMissingColumnNames);
allowMissingColumnNames, ignoreHeaderCase);
}

/**
Expand All @@ -1177,7 +1219,7 @@ public CSVFormat withQuote(final Character quoteChar) {
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);
}

/**
Expand Down Expand Up @@ -1215,7 +1257,7 @@ public CSVFormat withRecordSeparator(final char recordSeparator) {
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);
}

/**
Expand All @@ -1242,6 +1284,6 @@ public CSVFormat withSkipHeaderRecord() {
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);
}
}
5 changes: 4 additions & 1 deletion src/main/java/org/apache/commons/csv/CSVParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TreeMap;

import static org.apache.commons.csv.Token.Type.*;

Expand Down Expand Up @@ -378,7 +379,9 @@ private Map<String, Integer> initializeHeader() throws IOException {
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) {
Expand Down
11 changes: 11 additions & 0 deletions src/test/java/org/apache/commons/csv/CSVParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -973,4 +973,15 @@ private void validateRecordPosition(final String lineSeparator) throws IOExcepti

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"));
}
}