2012/11/17 <[email protected]>
> Author: ggregory
> Date: Sat Nov 17 18:00:38 2012
> New Revision: 1410759
>
> URL: http://svn.apache.org/viewvc?rev=1410759&view=rev
> Log:
> [CSV-68] Use the Builder pattern for CSVFormat.
>
> Modified:
>
> commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java
>
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatBuilderTest.java
>
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatTest.java
>
> 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=1410759&r1=1410758&r2=1410759&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
> Sat Nov 17 18:00:38 2012
> @@ -29,12 +29,13 @@ import java.io.IOException;
> import java.io.Reader;
> import java.io.Serializable;
> import java.io.StringWriter;
> +import java.util.Arrays;
>
> /**
> * The format specification of a CSV file.
> *
> * This class is immutable.
> - *
> + *
> * @version $Id$
> */
> public class CSVFormat implements Serializable {
> @@ -125,8 +126,8 @@ public class CSVFormat implements Serial
>
> /**
> * Creates a new CSV format builds.
> - *
> - * @param delimiter
> + *
> + * @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
> */
> @@ -137,7 +138,7 @@ public class CSVFormat implements Serial
> public static CSVFormatBuilder newBuilder(final CSVFormat format) {
> return new CSVFormatBuilder(format);
> }
> -
> +
> /**
> * Standard comma separated format, as for {@link #RFC4180} but
> allowing blank lines.
> * <ul>
> @@ -158,7 +159,7 @@ public class CSVFormat implements Serial
> * the char used for value separation, must not be a line
> break character
> * @param quoteChar
> * the char used as value encapsulation marker
> - * @param quotePolicy
> + * @param quotePolicy
> * the quote policy
> * @param commentStart
> * the char used for comment identification
> @@ -174,10 +175,12 @@ public class CSVFormat implements Serial
> * the header
> * @throws IllegalArgumentException if the delimiter is a line break
> character
> */
> - 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)) {
> + 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))
> + {
> throw new IllegalArgumentException("The delimiter cannot be a
> line break");
> }
> this.delimiter = delimiter;
> @@ -188,7 +191,7 @@ public class CSVFormat implements Serial
> this.ignoreSurroundingSpaces = ignoreSurroundingSpaces;
> this.ignoreEmptyLines = ignoreEmptyLines;
> this.recordSeparator = lineSeparator;
> - this.header = header;
> + this.header = header == null ? null : header.clone();
>
Well, that looks a lot simpler :) Thanks Gary!
What else has to be done to finish CSV-68?
Regards,
Benedikt
> }
>
> /**
> @@ -373,7 +376,109 @@ public class CSVFormat implements Serial
> public Quote getQuotePolicy() {
> return quotePolicy;
> }
> -
> +
> + @Override
> + public int hashCode()
> + {
> + final int prime = 31;
> + int result = 1;
> +
> + result = prime * result + delimiter;
> + result = prime * result + ((quotePolicy == null) ? 0 :
> quotePolicy.hashCode());
> + result = prime * result + ((quoteChar == null) ? 0 :
> quoteChar.hashCode());
> + result = prime * result + ((commentStart == null) ? 0 :
> commentStart.hashCode());
> + result = prime * result + ((escape == null) ? 0 :
> escape.hashCode());
> + result = prime * result + (ignoreSurroundingSpaces ? 1231 : 1237);
> + result = prime * result + (ignoreEmptyLines ? 1231 : 1237);
> + result = prime * result + ((recordSeparator == null) ? 0 :
> recordSeparator.hashCode());
> + result = prime * result + Arrays.hashCode(header);
> + return result;
> + }
> +
> + @Override
> + public boolean equals(Object obj)
> + {
> + if (this == obj)
> + {
> + return true;
> + }
> + if (obj == null)
> + {
> + return false;
> + }
> + if (getClass() != obj.getClass())
> + {
> + return false;
> + }
> +
> + CSVFormat other = (CSVFormat) obj;
> + if (delimiter != other.delimiter)
> + {
> + return false;
> + }
> + if (quotePolicy != other.quotePolicy)
> + {
> + return false;
> + }
> + if (quoteChar == null)
> + {
> + if (other.quoteChar != null)
> + {
> + return false;
> + }
> + }
> + else if (!quoteChar.equals(other.quoteChar))
> + {
> + return false;
> + }
> + if (commentStart == null)
> + {
> + if (other.commentStart != null)
> + {
> + return false;
> + }
> + }
> + else if (!commentStart.equals(other.commentStart))
> + {
> + return false;
> + }
> + if (escape == null)
> + {
> + if (other.escape != null)
> + {
> + return false;
> + }
> + }
> + else if (!escape.equals(other.escape))
> + {
> + return false;
> + }
> + if (!Arrays.equals(header, other.header))
> + {
> + return false;
> + }
> + if (ignoreSurroundingSpaces != other.ignoreSurroundingSpaces)
> + {
> + return false;
> + }
> + if (ignoreEmptyLines != other.ignoreEmptyLines)
> + {
> + return false;
> + }
> + if (recordSeparator == null)
> + {
> + if (other.recordSeparator != null)
> + {
> + return false;
> + }
> + }
> + else if (!recordSeparator.equals(other.recordSeparator))
> + {
> + return false;
> + }
> + return true;
> + }
> +
> public static class CSVFormatBuilder {
>
> private char delimiter;
> @@ -393,7 +498,7 @@ public class CSVFormat implements Serial
> * the char used for value separation, must not be a
> line break character
> * @param quoteChar
> * the char used as value encapsulation marker
> - * @param quotePolicy
> + * @param quotePolicy
> * the quote policy
> * @param commentStart
> * the char used for comment identification
> @@ -410,8 +515,8 @@ public class CSVFormat implements Serial
> * @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,
> + 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");
> @@ -426,11 +531,11 @@ public class CSVFormat implements Serial
> this.recordSeparator = lineSeparator;
> this.header = header;
> }
> -
> +
> /**
> - *
> + *
> * Creates a CSVFormatBuilder, using the values of the given
> CSVFormat.
> - *
> + *
> * @param format
> * The format to use values from
> */
> @@ -443,8 +548,8 @@ public class CSVFormat implements Serial
>
> /**
> * Creates a basic CSVFormatBuilder.
> - *
> - * @param delimiter
> + *
> + * @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
> */
> @@ -457,35 +562,35 @@ public class CSVFormat implements Serial
> 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 +
> + 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 +
> + 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");
> }
> @@ -504,7 +609,7 @@ public class CSVFormat implements Serial
> if (isLineBreak(delimiter)) {
> throw new IllegalArgumentException("The delimiter cannot
> be a line break");
> }
> - this.delimiter = delimiter;
> + this.delimiter = delimiter;
> return this;
> }
>
> @@ -625,7 +730,7 @@ public class CSVFormat implements Serial
> this.header = header;
> return this;
> }
> -
> +
> /**
> * Sets the trimming behavior of the format.
> *
>
> Modified:
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatBuilderTest.java
> URL:
> http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatBuilderTest.java?rev=1410759&r1=1410758&r2=1410759&view=diff
>
> ==============================================================================
> ---
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatBuilderTest.java
> (original)
> +++
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatBuilderTest.java
> Sat Nov 17 18:00:38 2012
> @@ -21,9 +21,9 @@ import static org.apache.commons.csv.CSV
> import static org.apache.commons.csv.Constants.CR;
> import static org.apache.commons.csv.Constants.CRLF;
> import static org.apache.commons.csv.Constants.LF;
> -import static org.junit.Assert.assertArrayEquals;
> import static org.junit.Assert.assertEquals;
> import static org.junit.Assert.assertFalse;
> +import static org.junit.Assert.assertNotSame;
> import static org.junit.Assert.assertTrue;
>
> import org.apache.commons.csv.CSVFormat.CSVFormatBuilder;
> @@ -159,7 +159,7 @@ public class CSVFormatBuilderTest {
> @Test
> public void testCopiedFormatIsEqualToOriginal() {
> CSVFormat copyOfRCF4180 = CSVFormat.newBuilder(RFC4180).build();
> - assertEqualFormats(RFC4180, copyOfRCF4180);
> + assertEquals(RFC4180, copyOfRCF4180);
> }
>
> @Test
> @@ -168,16 +168,14 @@ public class CSVFormatBuilderTest {
> assertTrue(newFormat.getDelimiter() != RFC4180.getDelimiter());
> }
>
> - // FIXME implement equals on CSVFormat to allow use of
> Assert.assertEquals()
> - private static void assertEqualFormats(CSVFormat expected, CSVFormat
> acutal) {
> - assertEquals(expected.getCommentStart(),
> acutal.getCommentStart());
> - assertEquals(expected.getDelimiter(), acutal.getDelimiter());
> - assertEquals(expected.getEscape(), acutal.getEscape());
> - assertArrayEquals(expected.getHeader(), acutal.getHeader());
> - assertEquals(expected.getIgnoreEmptyLines(),
> acutal.getIgnoreEmptyLines());
> - assertEquals(expected.getIgnoreSurroundingSpaces(),
> acutal.getIgnoreSurroundingSpaces());
> - assertEquals(expected.getQuoteChar(), acutal.getQuoteChar());
> - assertEquals(expected.getQuotePolicy(), acutal.getQuotePolicy());
> - assertEquals(expected.getRecordSeparator(),
> acutal.getRecordSeparator());
> + @Test
> + public void testHeaderReferenceCannotEscape() {
> + String[] header = new String[]{"one", "tow", "three"};
> + builder.withHeader(header);
> +
> + CSVFormat firstFormat = builder.build();
> + CSVFormat secondFormat = builder.build();
> + assertNotSame(header, firstFormat.getHeader());
> + assertNotSame(firstFormat, secondFormat.getHeader());
> }
> }
>
> Modified:
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatTest.java
> URL:
> http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatTest.java?rev=1410759&r1=1410758&r2=1410759&view=diff
>
> ==============================================================================
> ---
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatTest.java
> (original)
> +++
> commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVFormatTest.java
> Sat Nov 17 18:00:38 2012
> @@ -18,6 +18,7 @@
> package org.apache.commons.csv;
>
> import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertFalse;
> import static org.junit.Assert.assertNotNull;
>
> import java.io.ByteArrayInputStream;
> @@ -65,4 +66,153 @@ public class CSVFormatTest {
> assertEquals("trim",
> CSVFormat.DEFAULT.getIgnoreSurroundingSpaces(),
> format.getIgnoreSurroundingSpaces());
> assertEquals("empty lines",
> CSVFormat.DEFAULT.getIgnoreEmptyLines(), format.getIgnoreEmptyLines());
> }
> +
> + @Test
> + public void testEquals() {
> + CSVFormat right = CSVFormat.DEFAULT;
> + CSVFormat left = CSVFormat.newBuilder().build();
> +
> + assertFalse(right.equals(null));
> + assertFalse(right.equals("A String Instance"));
> +
> + assertEquals(right, right);
> + assertEquals(right, left);
> + assertEquals(left, right);
> +
> + assertEquals(right.hashCode(), right.hashCode());
> + assertEquals(right.hashCode(), left.hashCode());
> + }
> +
> + @Test
> + public void testEqualsDelimiter() {
> + CSVFormat right = CSVFormat.newBuilder('!').build();
> + CSVFormat left = CSVFormat.newBuilder('?').build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsQuoteChar() {
> + CSVFormat right =
> CSVFormat.newBuilder('\'').withQuoteChar('"').build();
> + CSVFormat left =
> CSVFormat.newBuilder(right).withQuoteChar('!').build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsQuotePolicy() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withQuotePolicy(Quote.MINIMAL)
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsCommentStart() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .withCommentStart('#')
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withCommentStart('!')
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsEscape() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .withCommentStart('#')
> + .withEscape('+')
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withEscape('!')
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsIgnoreSurroundingSpaces() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .withCommentStart('#')
> + .withEscape('+')
> + .withIgnoreSurroundingSpaces(true)
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withIgnoreSurroundingSpaces(false)
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsIgnoreEmptyLines() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .withCommentStart('#')
> + .withEscape('+')
> + .withIgnoreSurroundingSpaces(true)
> + .withIgnoreEmptyLines(true)
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withIgnoreEmptyLines(false)
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsRecordSeparator() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .withCommentStart('#')
> + .withEscape('+')
> + .withIgnoreSurroundingSpaces(true)
> + .withIgnoreEmptyLines(true)
> + .withRecordSeparator('*')
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withRecordSeparator('!')
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + @Test
> + public void testEqualsHeader() {
> + CSVFormat right = CSVFormat.newBuilder('\'')
> + .withQuoteChar('"')
> + .withQuotePolicy(Quote.ALL)
> + .withCommentStart('#')
> + .withEscape('+')
> + .withIgnoreSurroundingSpaces(true)
> + .withIgnoreEmptyLines(true)
> + .withRecordSeparator('*')
> + .withHeader("One", "Two", "Three")
> + .build();
> + CSVFormat left = CSVFormat.newBuilder(right)
> + .withHeader("Three", "Two", "One")
> + .build();
> +
> + assertNotEquals(right, left);
> + }
> +
> + private static void assertNotEquals(Object right, Object left) {
> + assertFalse(right.equals(left));
> + assertFalse(left.equals(right));
> + }
> }
>
>
>