You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by st...@apache.org on 2018/02/09 16:10:59 UTC

[1/3] commons-csv git commit: CSV-216 add mutator functions

Repository: commons-csv
Updated Branches:
  refs/heads/CSV-216-with [created] c66ea98c0


CSV-216 add mutator functions

if the record is already mutable, they will return
the current object, otherwise a copy will be made
using private CSVMutableRecord subclass.

The method mutable() and immutable() can be used to ensure
either semantics.


Project: http://git-wip-us.apache.org/repos/asf/commons-csv/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-csv/commit/bb949adb
Tree: http://git-wip-us.apache.org/repos/asf/commons-csv/tree/bb949adb
Diff: http://git-wip-us.apache.org/repos/asf/commons-csv/diff/bb949adb

Branch: refs/heads/CSV-216-with
Commit: bb949adbcb519356aa0cf6c4f62ee0e3643b84ee
Parents: c290f13
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Feb 9 16:07:45 2018 +0000
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Feb 9 16:08:32 2018 +0000

----------------------------------------------------------------------
 .../apache/commons/csv/CSVMutableRecord.java    |  38 +++++--
 .../java/org/apache/commons/csv/CSVRecord.java  | 104 ++++++++++++++++++-
 2 files changed, 132 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-csv/blob/bb949adb/src/main/java/org/apache/commons/csv/CSVMutableRecord.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/csv/CSVMutableRecord.java b/src/main/java/org/apache/commons/csv/CSVMutableRecord.java
index b529cfb..a2105c8 100644
--- a/src/main/java/org/apache/commons/csv/CSVMutableRecord.java
+++ b/src/main/java/org/apache/commons/csv/CSVMutableRecord.java
@@ -19,7 +19,19 @@ package org.apache.commons.csv;
 
 import java.util.Map;
 
-public final class CSVMutableRecord extends CSVRecord {
+/**
+ * A mutable version of CSVRecord
+ * <p>
+ * As mutation is generally done within the parent {@link CSVRecord}, this 
+ * package-private class just includes more efficient versions of 
+ * mutator functions, bypassing the need to make copies 
+ * (except in {@link #immutable()}).
+ * <p>
+ * To enable generating CSVMutableRecord by default, set 
+ * {@link CSVFormat#withMutableRecords(boolean)} to <code>true</code>.
+ *
+ */
+final class CSVMutableRecord extends CSVRecord {
 
     private static final long serialVersionUID = 1L;
 
@@ -29,13 +41,25 @@ public final class CSVMutableRecord extends CSVRecord {
     }
 
     @Override
-    public void put(int index, String value) {
-        super.put(index, value);
+    public CSVMutableRecord withValue(int index, String value) {
+    	super.put(index, value);
+    	return this;
     }
-
+    
     @Override
-    public void put(String name, String value) {
-        super.put(name, value);
+    public CSVMutableRecord withValue(String name, String value) {
+    	super.put(name, value);
+    	return this;
+    }
+    
+    @Override
+    public CSVRecord withComment(String comment) {
+    	this.comment = comment;
+    	return this;
+    }    
+    
+    @Override
+    boolean isMutable() {
+    	return true;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/commons-csv/blob/bb949adb/src/main/java/org/apache/commons/csv/CSVRecord.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/csv/CSVRecord.java b/src/main/java/org/apache/commons/csv/CSVRecord.java
index 35812ae..8b08353 100644
--- a/src/main/java/org/apache/commons/csv/CSVRecord.java
+++ b/src/main/java/org/apache/commons/csv/CSVRecord.java
@@ -36,8 +36,11 @@ public class CSVRecord implements Serializable, Iterable<String> {
 
     private final long characterPosition;
 
-    /** The accumulated comments (if any) */
-    private final String comment;
+    /** The accumulated comments (if any)
+     *
+     * package-private so it can be mutated by {@link CSVMutableRecord}
+     */
+    String comment;
 
     /** The column name to index mapping. */
     private final Map<String, Integer> mapping;
@@ -182,6 +185,28 @@ public class CSVRecord implements Serializable, Iterable<String> {
     }
 
     /**
+     * Return an immutable CSVRecord.
+     * <p>
+     * Immutable records have fixed values and are thus thread-safe. 
+     * <p>
+     * If this record is already immutable, it will be returned directly, 
+     * otherwise a copy of its current values will be made. 
+     * <p>
+     * Use {@link #mutable()} or {@link #withValue(int, String)} to get a mutable CSVRecord. 
+     * 
+     * @return Am immutable CSVRecord
+     */    
+    public CSVRecord immutable() {
+    	if (isMutable()) {
+	    	// Subclass is probably CSVMutableRecord, freeze values
+	    	String[] frozenValue = Arrays.copyOf(values, values.length);
+	    	return new CSVRecord(frozenValue, mapping, comment, recordNumber, characterPosition);
+    	} else {
+    		return this;    		
+    	}
+    }    
+    
+    /**
      * Checks whether a given column is mapped, i.e. its name has been defined to the parser.
      *
      * @param name
@@ -191,7 +216,11 @@ public class CSVRecord implements Serializable, Iterable<String> {
     public boolean isMapped(final String name) {
         return mapping != null && mapping.containsKey(name);
     }
-
+    
+    boolean isMutable() { 
+    	return false;
+    }
+    
     /**
      * Checks whether a given columns is mapped and has a value.
      *
@@ -212,6 +241,28 @@ public class CSVRecord implements Serializable, Iterable<String> {
     public Iterator<String> iterator() {
         return toList().iterator();
     }
+    
+    /**
+     * Return a mutable CSVRecord.
+     * <p>
+     * Mutable records have more efficient implementations of 
+     * {@link #withValue(int, String)} and {@link #withValue(String, String)}
+     * for when multiple modifications are to be done on the same record.
+     * <p>
+     * If this record is already mutable, it will be returned directly, otherwise
+     * a copy of its values will be made for the new mutable record. 
+     * <p>
+     * Use {@link #immutable()} to freeze a mutable CSVRecord. 
+     * 
+     * @return A mutable CSVRecord
+     */
+    public CSVRecord mutable() {
+    	if (isMutable()) {
+    		return this;
+    	}
+		String[] newValues = Arrays.copyOf(values, values.length);
+    	return new CSVMutableRecord(newValues, mapping, comment, recordNumber, characterPosition);
+	}    
 
     void put(final int index, String value) {
         values[index] = value;
@@ -286,5 +337,52 @@ public class CSVRecord implements Serializable, Iterable<String> {
     String[] values() {
         return values;
     }
+    
+    /**
+     * Return a CSVRecord with the given column value set.
+     * 
+     * @param name
+     *            the name of the column to set.
+     * @param value
+     * 			  The new value to set
+     * @throws IllegalStateException
+     *             if no header mapping was provided
+     * @throws IllegalArgumentException
+     *             if {@code name} is not mapped or if the record is inconsistent
+     * @return A mutated CSVRecord
+     */
+    public CSVRecord withValue(String name, String value) {    	
+    	CSVRecord r = mutable();
+    	r.put(name,  value);
+    	return r;
+    }
+
+    /**
+     * Return a CSVRecord with the given column value set.
+     * 
+     * @param index
+     *            the column to be retrieved.
+     * @param value
+     * 			  The new value to set
+     * @return A mutated CSVRecord
+     */    
+    public CSVRecord withValue(int index, String value) {
+    	CSVRecord r = mutable();
+    	r.put(index,  value);
+    	return r;
+    }
+    
+    /**
+     * Return a CSVRecord with the given comment set.
+     * 
+     * @param comment
+     * 			the comment to set, or <code>null</code> for no comment.
+     * @return A mutated CSVRecord
+     */
+    public CSVRecord withComment(String comment) {
+    	CSVRecord r = mutable();
+    	r.comment = comment;
+    	return r;
+    }
 
 }


[3/3] commons-csv git commit: CSV-216 test mutators

Posted by st...@apache.org.
CSV-216 test mutators


Project: http://git-wip-us.apache.org/repos/asf/commons-csv/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-csv/commit/c66ea98c
Tree: http://git-wip-us.apache.org/repos/asf/commons-csv/tree/c66ea98c
Diff: http://git-wip-us.apache.org/repos/asf/commons-csv/diff/c66ea98c

Branch: refs/heads/CSV-216-with
Commit: c66ea98c0fdc344fc919b228988c695c4b62c442
Parents: 6eebeb0
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Feb 9 16:09:41 2018 +0000
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Feb 9 16:09:41 2018 +0000

----------------------------------------------------------------------
 .../commons/csv/CSVMutableRecordTest.java       | 10 ++++
 .../org/apache/commons/csv/CSVRecordTest.java   | 58 ++++++++++++++++++++
 2 files changed, 68 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-csv/blob/c66ea98c/src/test/java/org/apache/commons/csv/CSVMutableRecordTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/csv/CSVMutableRecordTest.java b/src/test/java/org/apache/commons/csv/CSVMutableRecordTest.java
index 8f97dcd..08770fd 100644
--- a/src/test/java/org/apache/commons/csv/CSVMutableRecordTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVMutableRecordTest.java
@@ -1,9 +1,19 @@
 package org.apache.commons.csv;
 
+import static org.junit.Assert.assertTrue;
+
 import org.junit.Assert;
+import org.junit.Test;
 
 public class CSVMutableRecordTest extends CSVRecordTest {
 
+	@Override
+    @Test
+    public void isMutable() { 
+    	assertTrue(record.isMutable());
+    	assertTrue(recordWithHeader.isMutable());
+    }
+
     @Override
     protected CSVFormat createCommaFormat() {
         return super.createCommaFormat().withMutableRecords(true);

http://git-wip-us.apache.org/repos/asf/commons-csv/blob/c66ea98c/src/test/java/org/apache/commons/csv/CSVRecordTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/csv/CSVRecordTest.java b/src/test/java/org/apache/commons/csv/CSVRecordTest.java
index cc3f3c6..69f124d 100644
--- a/src/test/java/org/apache/commons/csv/CSVRecordTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVRecordTest.java
@@ -19,7 +19,9 @@ package org.apache.commons.csv;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
@@ -188,6 +190,62 @@ public class CSVRecordTest {
     }
 
     @Test
+    public void isMutable() { 
+    	assertFalse(record.isMutable());
+    	assertFalse(recordWithHeader.isMutable());
+    }
+    
+    @Test
+    public void testMutable() throws Exception {
+    	CSVRecord mutable = record.mutable();
+    	assertTrue(mutable.isMutable());
+    	if (record.isMutable()) { 
+    		assertSame(record, mutable);
+    	} else {    	
+    		assertNotSame(record, mutable);
+    	}    	
+    }
+    
+    @Test
+    public void testImmutable() throws Exception {
+    	CSVRecord immutable = record.immutable();
+    	assertFalse(immutable.isMutable());
+    	assertSame(immutable, immutable.immutable());
+    	assertNotSame(immutable, immutable.mutable());
+    	if (record.isMutable()) { 
+    		assertNotSame(record, immutable);
+    	} else {    	
+    		assertSame(record, immutable);
+    	}
+    }
+    
+    @Test
+    public void testWithValue() throws Exception {
+    	assertEquals("A", record.get(0));
+    	CSVRecord newR = record.withValue(0, "X");
+    	assertEquals("X", newR.get(0));    	
+    	if (record.isMutable()) {
+    		assertSame(record, newR);
+    	} else {
+    		// unchanged
+    		assertEquals("A", record.get(0));
+    	}
+    }
+    
+    @Test
+    public void testWithValueName() throws Exception {
+    	assertEquals("B", recordWithHeader.get("second"));
+    	CSVRecord newR = recordWithHeader.withValue("second", "Y");
+    	assertEquals("Y", newR.get("second"));    	
+    	if (record.isMutable()) {
+    		assertSame(recordWithHeader, newR);
+    	} else {
+    		// unchanged
+    		assertEquals("B", recordWithHeader.get("second"));
+    	}
+    }
+    
+    @Test
     public void testToMapWithNoHeader() throws Exception {
         try (final CSVParser parser = CSVParser.parse("a,b", createCommaFormat())) {
             final CSVRecord shortRec = parser.iterator().next();


[2/3] commons-csv git commit: CSV-216: Avoid references to CSVMutableRecord

Posted by st...@apache.org.
CSV-216: Avoid references to CSVMutableRecord

as mutator functions are directly in CSVRecord


Project: http://git-wip-us.apache.org/repos/asf/commons-csv/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-csv/commit/6eebeb04
Tree: http://git-wip-us.apache.org/repos/asf/commons-csv/tree/6eebeb04
Diff: http://git-wip-us.apache.org/repos/asf/commons-csv/diff/6eebeb04

Branch: refs/heads/CSV-216-with
Commit: 6eebeb0480a2376e928214e08e1279f0c337aad9
Parents: bb949ad
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Feb 9 16:09:19 2018 +0000
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Feb 9 16:09:19 2018 +0000

----------------------------------------------------------------------
 src/main/java/org/apache/commons/csv/CSVFormat.java | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-csv/blob/6eebeb04/src/main/java/org/apache/commons/csv/CSVFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java
index 2292081..6a0713d 100644
--- a/src/main/java/org/apache/commons/csv/CSVFormat.java
+++ b/src/main/java/org/apache/commons/csv/CSVFormat.java
@@ -626,7 +626,7 @@ public final class CSVFormat implements Serializable {
      * @param autoFlush
      * 	TODO
      * @param mutableRecords
-     * 	           if {@code true}, return {@link CSVMutableRecord} 
+     * 	           if {@code true}, {@link CSVRecord}s are {@link CSVRecord#mutable()} by default, otherwise immutable 
      * 
      * @throws IllegalArgumentException
      *             if the delimiter is a line break character
@@ -1808,16 +1808,16 @@ public final class CSVFormat implements Serializable {
     }
 
     /**
-     * Returns a new {@code CSVFormat} with whether to generate CSVRecord or CSVMutableRecord.
+     * Returns a new {@code CSVFormat} with mutable or immutable records by default.
      * <ul>
-     * <li><strong>Reading:</strong> Whether to generate CSVRecord or CSVMutableRecord.</li>
+     * <li><strong>Reading:</strong> Mutable by default.</li>
      * <li><strong>Writing:</strong> No effect.</li>
      * </ul>
      *
      * @param mutableRecords
-     *            whether to generate CSVRecord or CSVMutableRecord
+     *            If true, parsed @link CSVRecord}s are {@link CSVRecord#mutable()}, otherwise {@link CSVRecord#immutable()}.
      *
-     * @return A new CSVFormat that is equal to this but with setting to generate CSVRecord or CSVMutableRecord.
+     * @return A new CSVFormat that is equal to this but with setting to generate mutable/immutable records.
      */
     public CSVFormat withMutableRecords(final boolean mutableRecords) {
         return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,