[CSV-216] Allow for mutable CSV records.
This commit is contained in:
parent
259812ec0a
commit
b23f963e8d
|
@ -242,7 +242,7 @@ public final class CSVFormat implements Serializable {
|
||||||
* @see Predefined#Default
|
* @see Predefined#Default
|
||||||
*/
|
*/
|
||||||
public static final CSVFormat DEFAULT = new CSVFormat(COMMA, DOUBLE_QUOTE_CHAR, null, null, null, false, true, CRLF,
|
public static final CSVFormat DEFAULT = new CSVFormat(COMMA, DOUBLE_QUOTE_CHAR, null, null, null, false, true, CRLF,
|
||||||
null, null, null, false, false, false, false, false);
|
null, null, null, false, false, false, false, false, false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel file format (using a comma as the value delimiter). Note that the actual value delimiter used by Excel is
|
* Excel file format (using a comma as the value delimiter). Note that the actual value delimiter used by Excel is
|
||||||
|
@ -537,7 +537,7 @@ public final class CSVFormat implements Serializable {
|
||||||
*/
|
*/
|
||||||
public static CSVFormat newFormat(final char delimiter) {
|
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, false, false);
|
false, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -570,6 +570,8 @@ public final class CSVFormat implements Serializable {
|
||||||
|
|
||||||
private final boolean ignoreSurroundingSpaces; // Should leading/trailing spaces be ignored around values?
|
private final boolean ignoreSurroundingSpaces; // Should leading/trailing spaces be ignored around values?
|
||||||
|
|
||||||
|
private final boolean mutableRecords;
|
||||||
|
|
||||||
private final String nullString; // the string to be used for null values
|
private final String nullString; // the string to be used for null values
|
||||||
|
|
||||||
private final Character quoteCharacter; // null if quoting is disabled
|
private final Character quoteCharacter; // null if quoting is disabled
|
||||||
|
@ -619,6 +621,7 @@ public final class CSVFormat implements Serializable {
|
||||||
* TODO
|
* TODO
|
||||||
* @param trailingDelimiter
|
* @param trailingDelimiter
|
||||||
* TODO
|
* TODO
|
||||||
|
* @param mutableRecords TODO
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the delimiter is a line break character
|
* if the delimiter is a line break character
|
||||||
*/
|
*/
|
||||||
|
@ -627,7 +630,7 @@ public final class CSVFormat implements Serializable {
|
||||||
final boolean ignoreEmptyLines, final String recordSeparator, final String nullString,
|
final boolean ignoreEmptyLines, final String recordSeparator, final String nullString,
|
||||||
final Object[] headerComments, final String[] header, final boolean skipHeaderRecord,
|
final Object[] headerComments, final String[] header, final boolean skipHeaderRecord,
|
||||||
final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final boolean trim,
|
final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final boolean trim,
|
||||||
final boolean trailingDelimiter) {
|
final boolean trailingDelimiter, boolean mutableRecords) {
|
||||||
this.delimiter = delimiter;
|
this.delimiter = delimiter;
|
||||||
this.quoteCharacter = quoteChar;
|
this.quoteCharacter = quoteChar;
|
||||||
this.quoteMode = quoteMode;
|
this.quoteMode = quoteMode;
|
||||||
|
@ -644,6 +647,7 @@ public final class CSVFormat implements Serializable {
|
||||||
this.ignoreHeaderCase = ignoreHeaderCase;
|
this.ignoreHeaderCase = ignoreHeaderCase;
|
||||||
this.trailingDelimiter = trailingDelimiter;
|
this.trailingDelimiter = trailingDelimiter;
|
||||||
this.trim = trim;
|
this.trim = trim;
|
||||||
|
this.mutableRecords = mutableRecords;
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -927,6 +931,10 @@ public final class CSVFormat implements Serializable {
|
||||||
return escapeCharacter != null;
|
return escapeCharacter != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMutableRecords() {
|
||||||
|
return mutableRecords;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a nullString has been defined.
|
* Returns whether a nullString has been defined.
|
||||||
*
|
*
|
||||||
|
@ -1431,7 +1439,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withAllowMissingColumnNames(final boolean allowMissingColumnNames) {
|
public CSVFormat withAllowMissingColumnNames(final boolean allowMissingColumnNames) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1466,7 +1474,7 @@ public final class CSVFormat implements Serializable {
|
||||||
}
|
}
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1484,7 +1492,7 @@ public final class CSVFormat implements Serializable {
|
||||||
}
|
}
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1515,7 +1523,7 @@ public final class CSVFormat implements Serializable {
|
||||||
}
|
}
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces,
|
||||||
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
|
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
|
||||||
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1670,7 +1678,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withHeader(final String... header) {
|
public CSVFormat withHeader(final String... header) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1691,7 +1699,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withHeaderComments(final Object... headerComments) {
|
public CSVFormat withHeaderComments(final Object... headerComments) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1716,7 +1724,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) {
|
public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1742,7 +1750,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withIgnoreHeaderCase(final boolean ignoreHeaderCase) {
|
public CSVFormat withIgnoreHeaderCase(final boolean ignoreHeaderCase) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1767,7 +1775,25 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) {
|
public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@code CSVFormat} with whether to generate CSVRecord or CSVMutableRecord.
|
||||||
|
* <ul>
|
||||||
|
* <li><strong>Reading:</strong> Whether to generate CSVRecord or CSVMutableRecord.</li>
|
||||||
|
* <li><strong>Writing:</strong> No effect.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param mutableRecords
|
||||||
|
* whether to generate CSVRecord or CSVMutableRecord
|
||||||
|
*
|
||||||
|
* @return A new CSVFormat that is equal to this but with the specified null conversion string.
|
||||||
|
*/
|
||||||
|
public CSVFormat withMutableRecords(final boolean mutableRecords) {
|
||||||
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1786,7 +1812,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withNullString(final String nullString) {
|
public CSVFormat withNullString(final String nullString) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1817,7 +1843,7 @@ public final class CSVFormat implements Serializable {
|
||||||
}
|
}
|
||||||
return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces,
|
return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces,
|
||||||
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
|
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
|
||||||
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1831,7 +1857,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withQuoteMode(final QuoteMode quoteModePolicy) {
|
public CSVFormat withQuoteMode(final QuoteMode quoteModePolicy) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteModePolicy, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteModePolicy, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1869,7 +1895,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withRecordSeparator(final String recordSeparator) {
|
public CSVFormat withRecordSeparator(final String recordSeparator) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1896,7 +1922,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withSkipHeaderRecord(final boolean skipHeaderRecord) {
|
public CSVFormat withSkipHeaderRecord(final boolean skipHeaderRecord) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1921,7 +1947,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withTrailingDelimiter(final boolean trailingDelimiter) {
|
public CSVFormat withTrailingDelimiter(final boolean trailingDelimiter) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1946,6 +1972,7 @@ public final class CSVFormat implements Serializable {
|
||||||
public CSVFormat withTrim(final boolean trim) {
|
public CSVFormat withTrim(final boolean trim) {
|
||||||
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
|
||||||
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
|
||||||
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
|
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, mutableRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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.apache.commons.csv;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class CSVMutableRecord extends CSVRecord {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
CSVMutableRecord(String[] values, Map<String, Integer> mapping, String comment, long recordNumber,
|
||||||
|
long characterPosition) {
|
||||||
|
super(values, mapping, comment, recordNumber, characterPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(int index, String value) {
|
||||||
|
super.put(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(String name, String value) {
|
||||||
|
super.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -614,8 +614,10 @@ public final class CSVParser implements Iterable<CSVRecord>, Closeable {
|
||||||
if (!this.recordList.isEmpty()) {
|
if (!this.recordList.isEmpty()) {
|
||||||
this.recordNumber++;
|
this.recordNumber++;
|
||||||
final String comment = sb == null ? null : sb.toString();
|
final String comment = sb == null ? null : sb.toString();
|
||||||
result = new CSVRecord(this.recordList.toArray(new String[this.recordList.size()]), this.headerMap, comment,
|
String[] array = this.recordList.toArray(new String[this.recordList.size()]);
|
||||||
this.recordNumber, startCharPosition);
|
result = format.isMutableRecords()
|
||||||
|
? new CSVMutableRecord(array, this.headerMap, comment, this.recordNumber, startCharPosition)
|
||||||
|
: new CSVRecord(array, this.headerMap, comment, this.recordNumber, startCharPosition);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import java.util.Map.Entry;
|
||||||
/**
|
/**
|
||||||
* A CSV record parsed from a CSV file.
|
* A CSV record parsed from a CSV file.
|
||||||
*/
|
*/
|
||||||
public final class CSVRecord implements Serializable, Iterable<String> {
|
public class CSVRecord implements Serializable, Iterable<String> {
|
||||||
|
|
||||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||||
|
|
||||||
|
@ -95,22 +95,28 @@ public final class CSVRecord implements Serializable, Iterable<String> {
|
||||||
public String get(final String name) {
|
public String get(final String name) {
|
||||||
if (mapping == null) {
|
if (mapping == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"No header mapping was specified, the record values can't be accessed by name");
|
"No header mapping was specified, the record values can't be accessed by name");
|
||||||
}
|
|
||||||
final Integer index = mapping.get(name);
|
|
||||||
if (index == null) {
|
|
||||||
throw new IllegalArgumentException(String.format("Mapping for %s not found, expected one of %s", name,
|
|
||||||
mapping.keySet()));
|
|
||||||
}
|
}
|
||||||
|
final int intIndex = getIndex(name);
|
||||||
try {
|
try {
|
||||||
return values[index.intValue()];
|
return values[intIndex];
|
||||||
} catch (final ArrayIndexOutOfBoundsException e) {
|
} catch (final ArrayIndexOutOfBoundsException e) {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(
|
||||||
"Index for header '%s' is %d but CSVRecord only has %d values!", name, index,
|
String.format("Index for header '%s' is %d but CSVRecord only has %d values!", name, intIndex,
|
||||||
Integer.valueOf(values.length)));
|
Integer.valueOf(values.length)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getIndex(final String name) {
|
||||||
|
final Integer integerIndex = mapping.get(name);
|
||||||
|
if (integerIndex == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("Mapping for %s not found, expected one of %s", name, mapping.keySet()));
|
||||||
|
}
|
||||||
|
int intIndex = integerIndex.intValue();
|
||||||
|
return intIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the start position of this record as a character position in the source stream. This may or may not
|
* Returns the start position of this record as a character position in the source stream. This may or may not
|
||||||
* correspond to the byte position depending on the character set.
|
* correspond to the byte position depending on the character set.
|
||||||
|
@ -207,6 +213,14 @@ public final class CSVRecord implements Serializable, Iterable<String> {
|
||||||
return toList().iterator();
|
return toList().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void put(final int index, String value) {
|
||||||
|
values[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(final String name, String value) {
|
||||||
|
values[getIndex(name)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts all values of this record into the given Map.
|
* Puts all values of this record into the given Map.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.apache.commons.csv;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
public class CSVMutableRecordTest extends CSVRecordTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CSVFormat createCommaFormat() {
|
||||||
|
return super.createCommaFormat().withMutableRecords(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CSVFormat createDefaultFormat() {
|
||||||
|
return super.createDefaultFormat().withMutableRecords(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CSVRecord newRecord() {
|
||||||
|
return new CSVMutableRecord(values, null, null, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CSVRecord newRecordWithHeader() {
|
||||||
|
return new CSVMutableRecord(values, header, null, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validate(final CSVRecord anyRecord) {
|
||||||
|
Assert.assertEquals(CSVMutableRecord.class, anyRecord.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -38,19 +38,32 @@ public class CSVRecordTest {
|
||||||
|
|
||||||
private enum EnumFixture { UNKNOWN_COLUMN }
|
private enum EnumFixture { UNKNOWN_COLUMN }
|
||||||
|
|
||||||
private String[] values;
|
protected String[] values;
|
||||||
private CSVRecord record, recordWithHeader;
|
protected CSVRecord record, recordWithHeader;
|
||||||
private Map<String, Integer> header;
|
protected Map<String, Integer> header;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
values = new String[] { "A", "B", "C" };
|
values = new String[] { "A", "B", "C" };
|
||||||
record = new CSVRecord(values, null, null, 0, -1);
|
record = newRecord();
|
||||||
header = new HashMap<>();
|
header = new HashMap<>();
|
||||||
header.put("first", Integer.valueOf(0));
|
header.put("first", Integer.valueOf(0));
|
||||||
header.put("second", Integer.valueOf(1));
|
header.put("second", Integer.valueOf(1));
|
||||||
header.put("third", Integer.valueOf(2));
|
header.put("third", Integer.valueOf(2));
|
||||||
recordWithHeader = new CSVRecord(values, header, null, 0, -1);
|
recordWithHeader = newRecordWithHeader();
|
||||||
|
validate(recordWithHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CSVRecord newRecord() {
|
||||||
|
return new CSVRecord(values, null, null, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validate(final CSVRecord anyRecord) {
|
||||||
|
Assert.assertEquals(CSVRecord.class, anyRecord.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CSVRecord newRecordWithHeader() {
|
||||||
|
return new CSVRecord(values, header, null, 0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -143,7 +156,7 @@ public class CSVRecordTest {
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAndAddColumns() throws IOException {
|
public void testRemoveAndAddColumns() throws IOException {
|
||||||
// do:
|
// do:
|
||||||
try (final CSVPrinter printer = new CSVPrinter(new StringBuilder(), CSVFormat.DEFAULT)) {
|
try (final CSVPrinter printer = new CSVPrinter(new StringBuilder(), createDefaultFormat())) {
|
||||||
final Map<String, String> map = recordWithHeader.toMap();
|
final Map<String, String> map = recordWithHeader.toMap();
|
||||||
map.remove("OldColumn");
|
map.remove("OldColumn");
|
||||||
map.put("ZColumn", "NewValue");
|
map.put("ZColumn", "NewValue");
|
||||||
|
@ -151,10 +164,14 @@ public class CSVRecordTest {
|
||||||
final ArrayList<String> list = new ArrayList<>(map.values());
|
final ArrayList<String> list = new ArrayList<>(map.values());
|
||||||
Collections.sort(list);
|
Collections.sort(list);
|
||||||
printer.printRecord(list);
|
printer.printRecord(list);
|
||||||
Assert.assertEquals("A,B,C,NewValue" + CSVFormat.DEFAULT.getRecordSeparator(), printer.getOut().toString());
|
Assert.assertEquals("A,B,C,NewValue" + createDefaultFormat().getRecordSeparator(), printer.getOut().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected CSVFormat createDefaultFormat() {
|
||||||
|
return CSVFormat.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToMap() {
|
public void testToMap() {
|
||||||
final Map<String, String> map = this.recordWithHeader.toMap();
|
final Map<String, String> map = this.recordWithHeader.toMap();
|
||||||
|
@ -163,22 +180,28 @@ public class CSVRecordTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToMapWithShortRecord() throws Exception {
|
public void testToMapWithShortRecord() throws Exception {
|
||||||
try (final CSVParser parser = CSVParser.parse("a,b", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
|
try (final CSVParser parser = CSVParser.parse("a,b", createDefaultFormat().withHeader("A", "B", "C"))) {
|
||||||
final CSVRecord shortRec = parser.iterator().next();
|
final CSVRecord shortRec = parser.iterator().next();
|
||||||
|
validate(shortRec);
|
||||||
shortRec.toMap();
|
shortRec.toMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToMapWithNoHeader() throws Exception {
|
public void testToMapWithNoHeader() throws Exception {
|
||||||
try (final CSVParser parser = CSVParser.parse("a,b", CSVFormat.newFormat(','))) {
|
try (final CSVParser parser = CSVParser.parse("a,b", createCommaFormat())) {
|
||||||
final CSVRecord shortRec = parser.iterator().next();
|
final CSVRecord shortRec = parser.iterator().next();
|
||||||
|
validate(shortRec);
|
||||||
final Map<String, String> map = shortRec.toMap();
|
final Map<String, String> map = shortRec.toMap();
|
||||||
assertNotNull("Map is not null.", map);
|
assertNotNull("Map is not null.", map);
|
||||||
assertTrue("Map is empty.", map.isEmpty());
|
assertTrue("Map is empty.", map.isEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected CSVFormat createCommaFormat() {
|
||||||
|
return CSVFormat.newFormat(',');
|
||||||
|
}
|
||||||
|
|
||||||
private void validateMap(final Map<String, String> map, final boolean allowsNulls) {
|
private void validateMap(final Map<String, String> map, final boolean allowsNulls) {
|
||||||
assertTrue(map.containsKey("first"));
|
assertTrue(map.containsKey("first"));
|
||||||
assertTrue(map.containsKey("second"));
|
assertTrue(map.containsKey("second"));
|
||||||
|
|
Loading…
Reference in New Issue