[CSV-68] Use the Builder pattern for CSVFormat.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/csv/trunk@1409449 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gary D. Gregory 2012-11-14 21:50:36 +00:00
parent d266471b4c
commit 6a34b823c8
10 changed files with 522 additions and 446 deletions

View File

@ -30,6 +30,8 @@ import java.io.Reader;
import java.io.Serializable;
import java.io.StringWriter;
import org.apache.commons.csv.CSVFormat.CSVFormatBuilder;
/**
* The format specification of a CSV file.
*
@ -41,13 +43,6 @@ public class CSVFormat implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Constant char to use for disabling comments, escapes and encapsulation. The value -2 is used because it
* won't be confused with an EOF signal (-1), and because the Unicode value {@code FFFE} would be encoded as two chars
* (using surrogates) and thus there should never be a collision with a real text char.
*/
private static final char DISABLED = '\ufffe';
private final char delimiter;
private final Character quoteChar;
private final Quote quotePolicy;
@ -58,11 +53,6 @@ public class CSVFormat implements Serializable {
private final String recordSeparator; // for outputs
private final String[] header;
/**
* Starting format; used for creating other formats.
*/
private static final CSVFormat PRISTINE = new CSVFormat(DISABLED, null, null, null, null, false, false, null, null);
/**
* Comma separated format as defined by <a href="http://tools.ietf.org/html/rfc4180">RFC 4180</a>.
* <ul>
@ -72,10 +62,9 @@ public class CSVFormat implements Serializable {
* </ul>
*/
public static final CSVFormat RFC4180 =
PRISTINE
.withDelimiter(COMMA)
.withQuoteChar(DOUBLE_QUOTE)
.withRecordSeparator(CRLF);
defaults()
.withIgnoreEmptyLines(false)
.build();
/**
* Standard comma separated format, as for {@link #RFC4180} but allowing blank lines.
@ -87,8 +76,8 @@ public class CSVFormat implements Serializable {
* </ul>
*/
public static final CSVFormat DEFAULT = // TODO rename to something more meaningful
RFC4180
.withIgnoreEmptyLines(true);
defaults()
.build();
/**
* Excel file format (using a comma as the value delimiter). Note that the actual value delimiter used by Excel is
@ -108,19 +97,16 @@ public class CSVFormat implements Serializable {
* Note: this is currently the same as RFC4180
*/
public static final CSVFormat EXCEL =
PRISTINE
.withDelimiter(COMMA)
.withQuoteChar(DOUBLE_QUOTE)
.withRecordSeparator(CRLF);
defaults()
.withIgnoreEmptyLines(false)
.build();
/** Tab-delimited format, with quote; leading and trailing spaces ignored. */
public static final CSVFormat TDF =
PRISTINE
defaults()
.withDelimiter(TAB)
.withQuoteChar(DOUBLE_QUOTE)
.withIgnoreSurroundingSpaces(true)
.withIgnoreEmptyLines(true)
.withRecordSeparator(CRLF);
.build();
/**
* Default MySQL format used by the <tt>SELECT INTO OUTFILE</tt> and <tt>LOAD DATA INFILE</tt> operations. This is
@ -131,20 +117,36 @@ public class CSVFormat implements Serializable {
* http://dev.mysql.com/doc/refman/5.1/en/load-data.html</a>
*/
public static final CSVFormat MYSQL =
PRISTINE
defaults()
.withDelimiter(TAB)
.withQuoteChar(null)
.withEscape(ESCAPE)
.withRecordSeparator(LF);
.withIgnoreEmptyLines(false)
.withRecordSeparator(LF)
.build();
/**
* Creates a basic CSV format.
* Factory method for creating CSV formats.
*
* @param delimiter
* the char used for value separation, must not be a line break character
* @throws IllegalArgumentException if the delimiter is a line break character
*/
public CSVFormat(char delimiter){
this(delimiter, null, null, null, null, false, false, null, null);
public static CSVFormatBuilder newFormat(char delimiter) {
return new CSVFormatBuilder(delimiter);
}
/**
* Standard comma separated format, as for {@link #RFC4180} but allowing blank lines.
* <ul>
* <li>withDelimiter(',')</li>
* <li>withQuoteChar('"')</li>
* <li>withEmptyLinesIgnored(true)</li>
* <li>withLineSeparator(CRLF)</li>
* </ul>
*/
public static CSVFormatBuilder defaults() {
return new CSVFormatBuilder(COMMA, DOUBLE_QUOTE, null, null, null, false, true, CRLF, null);
}
/**
@ -170,8 +172,7 @@ public class CSVFormat implements Serializable {
* the header
* @throws IllegalArgumentException if the delimiter is a line break character
*/
// package protected for use by test code
CSVFormat(final char delimiter, final Character quoteChar, final Quote quotePolicy, final Character commentStart, final Character escape, final
private CSVFormat(final char delimiter, final Character quoteChar, final Quote quotePolicy, final Character commentStart, final Character escape, final
boolean ignoreSurroundingSpaces, final boolean ignoreEmptyLines, final String lineSeparator,
final String[] header) {
if (isLineBreak(delimiter)) {
@ -212,39 +213,6 @@ public class CSVFormat implements Serializable {
return c == LF || c == CR;
}
/**
* Verifies the consistency of the parameters and throws an IllegalStateException if necessary.
*
* @throws IllegalStateException
*/
void validate() throws IllegalStateException {
if (quoteChar != null && delimiter == quoteChar.charValue()) {
throw new IllegalStateException("The quoteChar character and the delimiter cannot be the same ('" + quoteChar + "')");
}
if (escape != null && delimiter == escape.charValue()) {
throw new IllegalStateException("The escape character and the delimiter cannot be the same ('" + escape + "')");
}
if (commentStart != null && delimiter == commentStart.charValue()) {
throw new IllegalStateException("The comment start character and the delimiter cannot be the same ('" + commentStart +
"')");
}
if (quoteChar != null && quoteChar.equals(commentStart)) {
throw new IllegalStateException("The comment start character and the quoteChar cannot be the same ('" + commentStart +
"')");
}
if (escape != null && escape.equals(commentStart)) {
throw new IllegalStateException("The comment start and the escape character cannot be the same ('" + commentStart + "')");
}
if (escape == null && quotePolicy == Quote.NONE) {
throw new IllegalStateException("No quotes mode set but no escape character is set");
}
}
/**
* Returns the character delimiting the values (typically ';', ',' or '\t').
*
@ -254,20 +222,6 @@ public class CSVFormat implements Serializable {
return delimiter;
}
/**
* Returns a copy of this format using the specified delimiter character.
*
* @param delimiter
* the delimiter character
* @return A copy of this format using the specified delimiter character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withDelimiter(final char delimiter) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Returns the character used to encapsulate values containing special characters.
*
@ -277,36 +231,6 @@ public class CSVFormat implements Serializable {
return quoteChar;
}
/**
* Returns a copy of this format using the specified quoteChar character.
*
* @param quoteChar
* the quoteChar character
* @return A copy of this format using the specified quoteChar character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withQuoteChar(final char quoteChar) {
return withQuoteChar(Character.valueOf(quoteChar));
}
/**
* Returns a copy of this format using the specified quoteChar character.
*
* @param quoteChar
* the quoteChar character
* @return A copy of this format using the specified quoteChar character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withQuoteChar(final Character quoteChar) {
if (isLineBreak(quoteChar)) {
throw new IllegalArgumentException("The quoteChar cannot be a line break");
}
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Returns whether an quoteChar has been defined.
*
@ -325,40 +249,6 @@ public class CSVFormat implements Serializable {
return commentStart;
}
/**
* Returns a copy of this format using the specified character as the comment start marker.
*
* Note that the comment introducer character is only recognised at the start of a line.
*
* @param commentStart
* the comment start marker
* @return A copy of this format using the specified character as the comment start marker
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withCommentStart(final char commentStart) {
return withCommentStart(Character.valueOf(commentStart));
}
/**
* Returns a copy of this format using the specified character as the comment start marker.
*
* Note that the comment introducer character is only recognised at the start of a line.
*
* @param commentStart
* the comment start marker
* @return A copy of this format using the specified character as the comment start marker
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withCommentStart(final Character commentStart) {
if (isLineBreak(commentStart)) {
throw new IllegalArgumentException("The comment start character cannot be a line break");
}
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Specifies whether comments are supported by this format.
*
@ -379,36 +269,6 @@ public class CSVFormat implements Serializable {
return escape;
}
/**
* Returns a copy of this format using the specified escape character.
*
* @param escape
* the escape character
* @return A copy of this format using the specified escape character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withEscape(final char escape) {
return withEscape(Character.valueOf(escape));
}
/**
* Returns a copy of this format using the specified escape character.
*
* @param escape
* the escape character
* @return A copy of this format using the specified escape character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormat withEscape(final Character escape) {
if (isLineBreak(escape)) {
throw new IllegalArgumentException("The escape character cannot be a line break");
}
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Returns whether escape are being processed.
*
@ -428,19 +288,6 @@ public class CSVFormat implements Serializable {
return ignoreSurroundingSpaces;
}
/**
* Returns a copy of this format with the specified trimming behavior.
*
* @param ignoreSurroundingSpaces
* the trimming behavior, <tt>true</tt> to remove the surrounding spaces, <tt>false</tt> to leave the
* spaces as is.
* @return A copy of this format with the specified trimming behavior.
*/
public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Specifies whether empty lines between records are ignored when parsing input.
*
@ -451,19 +298,6 @@ public class CSVFormat implements Serializable {
return ignoreEmptyLines;
}
/**
* Returns a copy of this format with the specified empty line skipping behavior.
*
* @param ignoreEmptyLines
* the empty line skipping behavior, <tt>true</tt> to ignore the empty lines between the records,
* <tt>false</tt> to translate empty lines to empty records.
* @return A copy of this format with the specified empty line skipping behavior.
*/
public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Returns the line separator delimiting output records.
*
@ -473,73 +307,10 @@ public class CSVFormat implements Serializable {
return recordSeparator;
}
/**
* Returns a copy of this format using the specified output record separator.
*
* @param recordSeparator
* the record separator to use for output.
*
* @return A copy of this format using the specified output record separator
*/
public CSVFormat withRecordSeparator(final char recordSeparator) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, String.valueOf(recordSeparator), header);
}
/**
* Returns a copy of this format using the specified output record separator.
*
* @param recordSeparator
* the record separator to use for output.
*
* @return A copy of this format using the specified output record separator
*/
public CSVFormat withRecordSeparator(final String recordSeparator) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Returns a copy of this format using the specified output quote policy.
*
* @param quotePolicy
* the quote policy to use for output.
*
* @return A copy of this format using the specified output line separator
*/
public CSVFormat withQuotePolicy(final Quote quotePolicy) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
String[] getHeader() {
return header;
}
/**
* Returns a copy of this format using the specified header. The header can either be parsed automatically from the
* input file with:
*
* <pre>
* CSVFormat format = aformat.withHeader();
* </pre>
*
* or specified manually with:
*
* <pre>
* CSVFormat format = aformat.withHeader(&quot;name&quot;, &quot;email&quot;, &quot;phone&quot;);
* </pre>
*
* @param header
* the header, <tt>null</tt> if disabled, empty if parsed automatically, user specified otherwise.
*
* @return A copy of this format using the specified header
*/
public CSVFormat withHeader(final String... header) {
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Parses the specified content.
*
@ -600,5 +371,307 @@ public class CSVFormat implements Serializable {
public Quote getQuotePolicy() {
return quotePolicy;
}
public static class CSVFormatBuilder {
private char delimiter;
private Character quoteChar;
private Quote quotePolicy;
private Character commentStart;
private Character escape;
private boolean ignoreSurroundingSpaces; // Should leading/trailing spaces be ignored around values?
private boolean ignoreEmptyLines;
private String recordSeparator; // for outputs
private String[] header;
/**
* Creates a customized CSV format.
*
* @param delimiter
* the char used for value separation, must not be a line break character
* @param quoteChar
* the char used as value encapsulation marker
* @param quotePolicy
* the quote policy
* @param commentStart
* the char used for comment identification
* @param escape
* the char used to escape special characters in values
* @param ignoreSurroundingSpaces
* <tt>true</tt> when whitespaces enclosing values should be ignored
* @param ignoreEmptyLines
* <tt>true</tt> when the parser should skip empty lines
* @param recordSeparator
* the line separator to use for output
* @param header
* the header
* @throws IllegalArgumentException if the delimiter is a line break character
*/
// package protected for use by test code
CSVFormatBuilder(final char delimiter, final Character quoteChar, final Quote quotePolicy, final Character commentStart, final Character escape, final
boolean ignoreSurroundingSpaces, final boolean ignoreEmptyLines, final String lineSeparator,
final String[] header) {
if (isLineBreak(delimiter)) {
throw new IllegalArgumentException("The delimiter cannot be a line break");
}
this.delimiter = delimiter;
this.quoteChar = quoteChar;
this.quotePolicy = quotePolicy;
this.commentStart = commentStart;
this.escape = escape;
this.ignoreSurroundingSpaces = ignoreSurroundingSpaces;
this.ignoreEmptyLines = ignoreEmptyLines;
this.recordSeparator = lineSeparator;
this.header = header;
}
/**
* Creates a basic CSVFormatBuilder.
*
* @param delimiter
* the char used for value separation, must not be a line break character
* @throws IllegalArgumentException if the delimiter is a line break character
*/
private CSVFormatBuilder(char delimiter){
this(delimiter, null, null, null, null, false, false, null, null);
}
public CSVFormat build() {
validate();
return new CSVFormat(delimiter, quoteChar, quotePolicy, commentStart, escape,
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, header);
}
/**
* Verifies the consistency of the parameters and throws an IllegalStateException if necessary.
*
* @throws IllegalStateException
*/
private void validate() throws IllegalStateException {
if (quoteChar != null && delimiter == quoteChar.charValue()) {
throw new IllegalStateException("The quoteChar character and the delimiter cannot be the same ('" + quoteChar + "')");
}
if (escape != null && delimiter == escape.charValue()) {
throw new IllegalStateException("The escape character and the delimiter cannot be the same ('" + escape + "')");
}
if (commentStart != null && delimiter == commentStart.charValue()) {
throw new IllegalStateException("The comment start character and the delimiter cannot be the same ('" + commentStart +
"')");
}
if (quoteChar != null && quoteChar.equals(commentStart)) {
throw new IllegalStateException("The comment start character and the quoteChar cannot be the same ('" + commentStart +
"')");
}
if (escape != null && escape.equals(commentStart)) {
throw new IllegalStateException("The comment start and the escape character cannot be the same ('" + commentStart + "')");
}
if (escape == null && quotePolicy == Quote.NONE) {
throw new IllegalStateException("No quotes mode set but no escape character is set");
}
}
/**
* Sets the delimiter of the format to the specified character.
*
* @param delimiter
* the delimiter character
* @return This builder with the specified character as delimiter
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withDelimiter(final char delimiter) {
if (isLineBreak(delimiter)) {
throw new IllegalArgumentException("The delimiter cannot be a line break");
}
this.delimiter = delimiter;
return this;
}
/**
* Sets the quoteChar of the format to the specified character.
*
* @param quoteChar
* the quoteChar character
* @return This builder with the specified character as quoteChar
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withQuoteChar(final char quoteChar) {
return withQuoteChar(Character.valueOf(quoteChar));
}
/**
* Sets the quoteChar of the format to the specified character.
*
* @param quoteChar
* the quoteChar character
* @return This builder with the specified character as quoteChar
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withQuoteChar(final Character quoteChar) {
if (isLineBreak(quoteChar)) {
throw new IllegalArgumentException("The quoteChar cannot be a line break");
}
this.quoteChar = quoteChar;
return this;
}
/**
* Sets the comment start marker of the format to the specified character.
*
* Note that the comment introducer character is only recognised at the start of a line.
*
* @param commentStart
* the comment start marker
* @return This builder with the specified character as the comment start marker
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withCommentStart(final char commentStart) {
return withCommentStart(Character.valueOf(commentStart));
}
/**
* Sets the comment start marker of the format to the specified character.
*
* Note that the comment introducer character is only recognised at the start of a line.
*
* @param commentStart
* the comment start marker
* @return This builder with the specified character as the comment start marker
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withCommentStart(final Character commentStart) {
if (isLineBreak(commentStart)) {
throw new IllegalArgumentException("The comment start character cannot be a line break");
}
this.commentStart = commentStart;
return this;
}
/**
* Sets the escape character of the format to the specified character.
*
* @param escape
* the escape character
* @return This builder with the specified character as the escape character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withEscape(final char escape) {
return withEscape(Character.valueOf(escape));
}
/**
* Sets the escape character of the format to the specified character.
*
* @param escape
* the escape character
* @return This builder with the specified character as the escape character
* @throws IllegalArgumentException
* thrown if the specified character is a line break
*/
public CSVFormatBuilder withEscape(final Character escape) {
if (isLineBreak(escape)) {
throw new IllegalArgumentException("The escape character cannot be a line break");
}
this.escape = escape;
return this;
}
/**
* Sets the header of the format. The header can either be parsed automatically from the
* input file with:
*
* <pre>
* CSVFormat format = aformat.withHeader();
* </pre>
*
* or specified manually with:
*
* <pre>
* CSVFormat format = aformat.withHeader(&quot;name&quot;, &quot;email&quot;, &quot;phone&quot;);
* </pre>
*
* @param header
* the header, <tt>null</tt> if disabled, empty if parsed automatically, user specified otherwise.
*
* @return This builder with the specified header
*/
public CSVFormatBuilder withHeader(final String... header) {
this.header = header;
return this;
}
/**
* Sets the trimming behavior of the format.
*
* @param ignoreSurroundingSpaces
* the trimming behavior, <tt>true</tt> to remove the surrounding spaces, <tt>false</tt> to leave the
* spaces as is.
* @return This builder with the specified trimming behavior.
*/
public CSVFormatBuilder withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) {
this.ignoreSurroundingSpaces = ignoreSurroundingSpaces;
return this;
}
/**
* Sets the empty line skipping behavior of the format.
*
* @param ignoreEmptyLines
* the empty line skipping behavior, <tt>true</tt> to ignore the empty lines between the records,
* <tt>false</tt> to translate empty lines to empty records.
* @return This builder with the specified empty line skipping behavior.
*/
public CSVFormatBuilder withIgnoreEmptyLines(final boolean ignoreEmptyLines) {
this.ignoreEmptyLines = ignoreEmptyLines;
return this;
}
/**
* Sets the record separator of the format to the specified character.
*
* @param recordSeparator
* the record separator to use for output.
*
* @return This builder with the the specified output record separator
*/
public CSVFormatBuilder withRecordSeparator(final char recordSeparator) {
return withRecordSeparator(String.valueOf(recordSeparator));
}
/**
* Sets the record separator of the format to the specified String.
*
* @param recordSeparator
* the record separator to use for output.
*
* @return This builder with the the specified output record separator
*/
public CSVFormatBuilder withRecordSeparator(final String recordSeparator) {
this.recordSeparator = recordSeparator;
return this;
}
/**
* Sets the output quote policy of the format to the specified value.
*
* @param quotePolicy
* the quote policy to use for output.
*
* @return This builder with the specified quote policy
*/
public CSVFormatBuilder withQuotePolicy(final Quote quotePolicy) {
this.quotePolicy = quotePolicy;
return this;
}
}
}

View File

@ -103,7 +103,6 @@ public class CSVParser implements Iterable<CSVRecord> {
* thrown if the parameters of the format are inconsistent
*/
public CSVParser(final Reader input, final CSVFormat format) throws IOException {
format.validate();
this.lexer = new CSVLexer(format, new ExtendedBufferedReader(input));
this.headerMap = initializeHeader(format);
}

View File

@ -59,7 +59,6 @@ public class CSVPrinter implements Flushable, Closeable {
public CSVPrinter(final Appendable out, final CSVFormat format) {
this.out = out;
this.format = format == null ? CSVFormat.DEFAULT : format;
this.format.validate();
}
// ======================================================

View File

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.csv.CSVFormat.CSVFormatBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -89,17 +90,18 @@ public class CSVFileParserTest {
assertTrue(testName+" require 1 param", split.length >= 1);
// first line starts with csv data file name
final BufferedReader csvFile = new BufferedReader(new FileReader(new File(BASE, split[0])));
CSVFormat fmt = new CSVFormat(',').withQuoteChar('"');
CSVFormatBuilder builder = CSVFormat.newFormat(',').withQuoteChar('"');
CSVFormat fmt = builder.build();
boolean checkComments = false;
for(int i=1; i < split.length; i++) {
final String option = split[i];
final String[] option_parts = option.split("=",2);
if ("IgnoreEmpty".equalsIgnoreCase(option_parts[0])){
fmt = fmt.withIgnoreEmptyLines(Boolean.parseBoolean(option_parts[1]));
fmt = builder.withIgnoreEmptyLines(Boolean.parseBoolean(option_parts[1])).build();
} else if ("IgnoreSpaces".equalsIgnoreCase(option_parts[0])) {
fmt = fmt.withIgnoreSurroundingSpaces(Boolean.parseBoolean(option_parts[1]));
fmt = builder.withIgnoreSurroundingSpaces(Boolean.parseBoolean(option_parts[1])).build();
} else if ("CommentStart".equalsIgnoreCase(option_parts[0])) {
fmt = fmt.withCommentStart(option_parts[1].charAt(0));
fmt = builder.withCommentStart(option_parts[1].charAt(0)).build();
} else if ("CheckComments".equalsIgnoreCase(option_parts[0])) {
checkComments = true;
} else {

View File

@ -0,0 +1,152 @@
/*
* 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 static org.apache.commons.csv.Constants.*;
import static org.junit.Assert.*;
import org.apache.commons.csv.CSVFormat.CSVFormatBuilder;
import org.junit.Before;
import org.junit.Test;
/**
*
*
* @version $Id$
*/
public class CSVFormatBuilderTest {
private CSVFormatBuilder builder;
@Before
public void setUp() throws Exception {
builder = new CSVFormatBuilder('+', '!', null, '#', '!', true, true, CRLF, null);
}
@Test
public void testDelimiter() {
assertEquals('?', builder.withDelimiter('?').build().getDelimiter());
}
@Test(expected = IllegalArgumentException.class)
public void testNewFormatLFThrowsException() {
CSVFormat.newFormat(LF);
}
@Test(expected = IllegalArgumentException.class)
public void testNewFormatCRThrowsException() {
CSVFormat.newFormat(CR);
}
@Test(expected = IllegalArgumentException.class)
public void testWithDelimiterLFThrowsException() {
builder.withDelimiter(LF).build();
}
@Test(expected = IllegalStateException.class)
public void testDelimiterSameAsEscapeThrowsException() {
builder.withDelimiter('!').withEscape('!').build();
}
@Test(expected = IllegalStateException.class)
public void testDelimiterSameAsCommentStartThrowsException() {
builder.withDelimiter('!').withCommentStart('!').build();
}
@Test
public void testQuoteChar() {
assertEquals('?', builder.withQuoteChar('?').build().getQuoteChar().charValue());
}
@Test(expected = IllegalStateException.class)
public void testQuoteCharSameAsCommentStartThrowsException() {
builder.withQuoteChar('!').withCommentStart('!').build();
}
@Test(expected = IllegalStateException.class)
public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType() {
// Cannot assume that callers won't use different Character objects
builder.withQuoteChar(new Character('!')).withCommentStart('!').build();
}
@Test(expected = IllegalStateException.class)
public void testQuoteCharSameAsDelimiterThrowsException() {
builder.withQuoteChar('!').withDelimiter('!').build();
}
@Test(expected = IllegalArgumentException.class)
public void testWithQuoteLFThrowsException() {
builder.withQuoteChar(LF).build();
}
@Test
public void testQuotePolicy() {
assertEquals(Quote.ALL, builder.withQuotePolicy(Quote.ALL).build().getQuotePolicy());
}
@Test(expected = IllegalStateException.class)
public void testQuotePolicyNoneWithoutEscapeThrowsException() {
CSVFormat.newFormat('!').withQuotePolicy(Quote.NONE).build();
}
@Test
public void testCommentStart() {
assertEquals('?', builder.withCommentStart('?').build().getCommentStart().charValue());
}
@Test(expected = IllegalArgumentException.class)
public void testWithCommentStartCRThrowsException() {
builder.withCommentStart(CR).build();
}
@Test
public void testRecoardSeparator() {
assertEquals("?", builder.withRecordSeparator("?").build().getRecordSeparator());
}
@Test
public void testEscape() {
assertEquals('?', builder.withEscape('?').build().getEscape().charValue());
}
@Test(expected = IllegalArgumentException.class)
public void testWithEscapeCRThrowsExceptions() {
builder.withEscape(CR).build();
}
@Test(expected = IllegalStateException.class)
public void testEscapeSameAsCommentStartThrowsException() {
builder.withEscape('!').withCommentStart('!').build();
}
@Test(expected = IllegalStateException.class)
public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType() {
// Cannot assume that callers won't use different Character objects
builder.withEscape(new Character('!')).withCommentStart(new Character('!')).build();
}
@Test
public void testIgnoreSurroundingSpaces() {
assertFalse(builder.withIgnoreSurroundingSpaces(false).build().getIgnoreSurroundingSpaces());
}
@Test
public void testIgnoreEmptyLines() {
assertFalse(builder.withIgnoreEmptyLines(false).build().getIgnoreEmptyLines());
}
}

View File

@ -29,6 +29,7 @@ import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.apache.commons.csv.CSVFormat.CSVFormatBuilder;
import org.junit.Test;
/**
@ -38,46 +39,6 @@ import org.junit.Test;
*/
public class CSVFormatTest {
@Test
public void testImmutalibity() {
final CSVFormat format = new CSVFormat('!', '!', Quote.MINIMAL, '!', '!', true, true, CRLF, null);
format.withDelimiter('?');
format.withQuoteChar('?');
format.withQuotePolicy(Quote.ALL);
format.withCommentStart('?');
format.withRecordSeparator("?");
format.withEscape('?');
format.withIgnoreSurroundingSpaces(false);
format.withIgnoreEmptyLines(false);
assertEquals('!', format.getDelimiter());
assertEquals('!', format.getQuoteChar().charValue());
assertEquals('!', format.getCommentStart().charValue());
assertEquals('!', format.getEscape().charValue());
assertEquals(CRLF, format.getRecordSeparator());
assertTrue(format.getIgnoreSurroundingSpaces());
assertTrue(format.getIgnoreEmptyLines());
assertEquals(Quote.MINIMAL, format.getQuotePolicy());
}
@Test
public void testMutators() {
final CSVFormat format = new CSVFormat('!', '!', null, '!', '!', true, true, CRLF, null);
assertEquals('?', format.withDelimiter('?').getDelimiter());
assertEquals('?', format.withQuoteChar('?').getQuoteChar().charValue());
assertEquals(Quote.ALL, format.withQuotePolicy(Quote.ALL).getQuotePolicy());
assertEquals('?', format.withCommentStart('?').getCommentStart().charValue());
assertEquals("?", format.withRecordSeparator("?").getRecordSeparator());
assertEquals('?', format.withEscape('?').getEscape().charValue());
assertFalse(format.withIgnoreSurroundingSpaces(false).getIgnoreSurroundingSpaces());
assertFalse(format.withIgnoreEmptyLines(false).getIgnoreEmptyLines());
}
@Test
public void testFormat() {
final CSVFormat format = CSVFormat.DEFAULT;
@ -87,116 +48,6 @@ public class CSVFormatTest {
assertEquals("\"x,y\",z", format.format("x,y", "z"));
}
@Test
public void testValidation() {
try {
new CSVFormat('\n');
fail();
} catch (final IllegalArgumentException e) {
// expected
}
try {
new CSVFormat('\r');
fail();
} catch (final IllegalArgumentException e) {
// expected
}
final CSVFormat format = CSVFormat.DEFAULT;
try {
format.withDelimiter('\n');
fail();
} catch (final IllegalArgumentException e) {
// expected
}
try {
format.withEscape('\r');
fail();
} catch (final IllegalArgumentException e) {
// expected
}
try {
format.withQuoteChar('\n');
fail();
} catch (final IllegalArgumentException e) {
// expected
}
try {
format.withCommentStart('\r');
fail();
} catch (final IllegalArgumentException e) {
// expected
}
try {
format.withDelimiter('!').withEscape('!').validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
try {
format.withDelimiter('!').withCommentStart('!').validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
try {
format.withQuoteChar('!').withCommentStart('!').validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
// Cannot assume that callers won't use different Character objects
try {
format.withQuoteChar(new Character('!')).withCommentStart('!').validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
format.withQuoteChar(null).withCommentStart(null).validate();
try {
format.withEscape('!').withCommentStart('!').validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
// Cannot assume that callers won't use different Character objects
try {
format.withEscape(new Character('!')).withCommentStart(new Character('!')).validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
format.withEscape(null).withCommentStart(null).validate();
try {
format.withQuoteChar('!').withDelimiter('!').validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
try {
format.withQuoteChar('!').withQuotePolicy(Quote.NONE).validate();
fail();
} catch (final IllegalStateException e) {
// expected
}
}
@SuppressWarnings("boxing") // no need to worry about boxing here
@Test
public void testSerialization() throws Exception {

View File

@ -51,7 +51,7 @@ public class CSVLexerTest {
@Test
public void testNextToken1() throws IOException {
final String code = "abc,def, hijk, lmnop, qrst,uv ,wxy ,z , ,";
final Lexer parser = getLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(true));
final Lexer parser = getLexer(code, CSVFormat.defaults().withIgnoreSurroundingSpaces(true).build());
assertTokenEquals(TOKEN, "abc", parser.nextToken(new Token()));
assertTokenEquals(TOKEN, "def", parser.nextToken(new Token()));
assertTokenEquals(TOKEN, "hijk", parser.nextToken(new Token()));
@ -83,7 +83,7 @@ public class CSVLexerTest {
"\n"+
"\n"+
"# Final comment\n"; // 7
final CSVFormat format = CSVFormat.DEFAULT.withCommentStart('#');
final CSVFormat format = CSVFormat.defaults().withCommentStart('#').build();
assertTrue("Should ignore empty lines", format.getIgnoreEmptyLines());
final Lexer parser = getLexer(code, format);
@ -126,7 +126,7 @@ public class CSVLexerTest {
"\n"+ // 6b
"\n"+ // 6c
"# Final comment\n"; // 7
final CSVFormat format = CSVFormat.DEFAULT.withCommentStart('#').withIgnoreEmptyLines(false);
final CSVFormat format = CSVFormat.defaults().withCommentStart('#').withIgnoreEmptyLines(false).build();
assertFalse("Should not ignore empty lines", format.getIgnoreEmptyLines());
final Lexer parser = getLexer(code, format);
@ -187,7 +187,7 @@ public class CSVLexerTest {
* \,,
*/
final String code = "a,\\,,b\\\\\n\\,,\\\nc,d\\\r\ne";
final CSVFormat format = CSVFormat.DEFAULT.withEscape('\\').withIgnoreEmptyLines(false);
final CSVFormat format = CSVFormat.defaults().withEscape('\\').withIgnoreEmptyLines(false).build();
assertTrue(format.isEscaping());
final Lexer parser = getLexer(code, format);
@ -204,7 +204,7 @@ public class CSVLexerTest {
@Test
public void testNextToken3BadEscaping() throws IOException {
final String code = "a,b,c\\";
final CSVFormat format = CSVFormat.DEFAULT.withEscape('\\');
final CSVFormat format = CSVFormat.defaults().withEscape('\\').build();
assertTrue(format.isEscaping());
final Lexer parser = getLexer(code, format);
@ -226,7 +226,7 @@ public class CSVLexerTest {
* a, " foo " ,b
*/
final String code = "a,\"foo\",b\na, \" foo\",b\na,\"foo \" ,b\na, \" foo \" ,b";
final Lexer parser = getLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(true));
final Lexer parser = getLexer(code, CSVFormat.defaults().withIgnoreSurroundingSpaces(true).build());
assertTokenEquals(TOKEN, "a", parser.nextToken(new Token()));
assertTokenEquals(TOKEN, "foo", parser.nextToken(new Token()));
assertTokenEquals(EORECORD, "b", parser.nextToken(new Token()));
@ -264,7 +264,7 @@ public class CSVLexerTest {
* ;;
*/
final String code = "a;'b and '' more\n'\n!comment;;;;\n;;";
final CSVFormat format = CSVFormat.DEFAULT.withDelimiter(';').withQuoteChar('\'').withCommentStart('!');
final CSVFormat format = CSVFormat.defaults().withDelimiter(';').withQuoteChar('\'').withCommentStart('!').build();
final Lexer parser = getLexer(code, format);
assertTokenEquals(TOKEN, "a", parser.nextToken(new Token()));
assertTokenEquals(EORECORD, "b and ' more\n", parser.nextToken(new Token()));

View File

@ -71,7 +71,7 @@ public class CSVParserTest {
@Test
public void testGetLine() throws IOException {
final CSVParser parser = new CSVParser(new StringReader(CSVINPUT), CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(true));
final CSVParser parser = new CSVParser(new StringReader(CSVINPUT), CSVFormat.defaults().withIgnoreSurroundingSpaces(true).build());
for (final String[] re : RESULT) {
assertArrayEquals(re, parser.nextRecord().values());
}
@ -81,7 +81,7 @@ public class CSVParserTest {
@Test
public void testGetRecords() throws IOException {
final CSVParser parser = new CSVParser(new StringReader(CSVINPUT), CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(true));
final CSVParser parser = new CSVParser(new StringReader(CSVINPUT), CSVFormat.defaults().withIgnoreSurroundingSpaces(true).build());
final List<CSVRecord> records = parser.getRecords();
assertEquals(RESULT.length, records.size());
assertTrue(records.size() > 0);
@ -312,8 +312,8 @@ public class CSVParserTest {
};
final CSVFormat format = new CSVFormat(',').withQuoteChar('\'').withEscape('/')
.withIgnoreEmptyLines(true).withRecordSeparator(CRLF);
final CSVFormat format = CSVFormat.newFormat(',').withQuoteChar('\'').withEscape('/')
.withIgnoreEmptyLines(true).withRecordSeparator(CRLF).build();
final CSVParser parser = new CSVParser(code, format);
final List<CSVRecord> records = parser.getRecords();
@ -342,8 +342,8 @@ public class CSVParserTest {
};
final CSVFormat format = new CSVFormat(',').withEscape('/')
.withIgnoreEmptyLines(true).withRecordSeparator(CRLF);
final CSVFormat format = CSVFormat.newFormat(',').withEscape('/')
.withIgnoreEmptyLines(true).withRecordSeparator(CRLF).build();
final CSVParser parser = new CSVParser(code, format);
final List<CSVRecord> records = parser.getRecords();
@ -381,7 +381,7 @@ public class CSVParserTest {
{"\n", " ", "#"},
};
format = CSVFormat.DEFAULT.withCommentStart('#');
format = CSVFormat.defaults().withCommentStart('#').build();
parser = new CSVParser(code, format);
records = parser.getRecords();
@ -481,7 +481,7 @@ public class CSVParserTest {
public void testHeader() throws Exception {
final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
final Iterator<CSVRecord> records = CSVFormat.DEFAULT.withHeader().parse(in).iterator();
final Iterator<CSVRecord> records = CSVFormat.defaults().withHeader().build().parse(in).iterator();
for (int i = 0; i < 2; i++) {
assertTrue(records.hasNext());
@ -498,7 +498,7 @@ public class CSVParserTest {
public void testHeaderComment() throws Exception {
final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
final Iterator<CSVRecord> records = CSVFormat.DEFAULT.withCommentStart('#').withHeader().parse(in).iterator();
final Iterator<CSVRecord> records = CSVFormat.defaults().withCommentStart('#').withHeader().build().parse(in).iterator();
for (int i = 0; i < 2; i++) {
assertTrue(records.hasNext());
@ -515,7 +515,7 @@ public class CSVParserTest {
public void testProvidedHeader() throws Exception {
final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
final Iterator<CSVRecord> records = CSVFormat.DEFAULT.withHeader("A", "B", "C").parse(in).iterator();
final Iterator<CSVRecord> records = CSVFormat.defaults().withHeader("A", "B", "C").build().parse(in).iterator();
for (int i = 0; i < 3; i++) {
assertTrue(records.hasNext());
@ -536,7 +536,7 @@ public class CSVParserTest {
public void testMappedButNotSetAsOutlook2007ContactExport() throws Exception {
final Reader in = new StringReader("a,b,c\n1,2\nx,y,z");
final Iterator<CSVRecord> records = CSVFormat.DEFAULT.withHeader("A", "B", "C").parse(in).iterator();
final Iterator<CSVRecord> records = CSVFormat.defaults().withHeader("A", "B", "C").build().parse(in).iterator();
// header record
assertTrue(records.hasNext());
@ -578,7 +578,7 @@ public class CSVParserTest {
}
public void testGetHeaderMap() throws Exception {
final CSVParser parser = new CSVParser("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"));
final CSVParser parser = new CSVParser("a,b,c\n1,2,3\nx,y,z", CSVFormat.defaults().withHeader("A", "B", "C").build());
final Map<String, Integer> headerMap = parser.getHeaderMap();
final Iterator<String> columnNames = headerMap.keySet().iterator();
// Headers are iterated in column order.
@ -622,7 +622,7 @@ public class CSVParserTest {
@Test
public void testGetRecordWithMultiiLineValues() throws Exception {
final CSVParser parser = new CSVParser("\"a\r\n1\",\"a\r\n2\"" + CRLF + "\"b\r\n1\",\"b\r\n2\"" + CRLF + "\"c\r\n1\",\"c\r\n2\"",
CSVFormat.DEFAULT.withRecordSeparator(CRLF));
CSVFormat.defaults().withRecordSeparator(CRLF).build());
CSVRecord record;
assertEquals(0, parser.getRecordNumber());
assertEquals(0, parser.getLineNumber());
@ -654,7 +654,7 @@ public class CSVParserTest {
}
private void validateRecordNumbers(String lineSeparator) throws IOException {
final CSVParser parser = new CSVParser("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.DEFAULT.withRecordSeparator(lineSeparator));
final CSVParser parser = new CSVParser("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.defaults().withRecordSeparator(lineSeparator).build());
CSVRecord record;
assertEquals(0, parser.getRecordNumber());
assertNotNull(record = parser.nextRecord());
@ -671,7 +671,7 @@ public class CSVParserTest {
}
private void validateLineNumbers(String lineSeparator) throws IOException {
final CSVParser parser = new CSVParser("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.DEFAULT.withRecordSeparator(lineSeparator));
final CSVParser parser = new CSVParser("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.defaults().withRecordSeparator(lineSeparator).build());
assertEquals(0, parser.getLineNumber());
assertNotNull(parser.nextRecord());
assertEquals(1, parser.getLineNumber());

View File

@ -220,7 +220,7 @@ public class CSVPrinterTest {
@Test
public void testMultiLineComment() throws IOException {
final StringWriter sw = new StringWriter();
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentStart('#'));
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.defaults().withCommentStart('#').build());
printer.printComment("This is a comment\non multiple lines");
assertEquals("# This is a comment" + recordSeparator + "# on multiple lines" + recordSeparator, sw.toString());
@ -293,7 +293,7 @@ public class CSVPrinterTest {
@Test
public void testQuoteAll() throws IOException {
final StringWriter sw = new StringWriter();
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuotePolicy(Quote.ALL));
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.defaults().withQuotePolicy(Quote.ALL).build());
printer.printRecord("a", "b\nc", "d");
assertEquals("\"a\",\"b\nc\",\"d\"" + recordSeparator, sw.toString());
}
@ -301,7 +301,7 @@ public class CSVPrinterTest {
@Test
public void testQuoteNonNumeric() throws IOException {
final StringWriter sw = new StringWriter();
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuotePolicy(Quote.NON_NUMERIC));
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.defaults().withQuotePolicy(Quote.NON_NUMERIC).build());
printer.printRecord("a", "b\nc", Integer.valueOf(1));
assertEquals("\"a\",\"b\nc\",1" + recordSeparator, sw.toString());
}
@ -317,7 +317,7 @@ public class CSVPrinterTest {
@Test
public void testSingleLineComment() throws IOException {
final StringWriter sw = new StringWriter();
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentStart('#'));
final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.defaults().withCommentStart('#').build());
printer.printComment("This is a comment");
assertEquals("# This is a comment" + recordSeparator, sw.toString());

View File

@ -66,7 +66,7 @@ public class PerformanceTest {
}
private long parse(final Reader in, boolean traverseColumns) throws IOException {
final CSVFormat format = CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(false);
final CSVFormat format = CSVFormat.defaults().withIgnoreSurroundingSpaces(false).build();
long recordCount = 0;
for (final CSVRecord record : format.parse(in)) {
recordCount++;