Repository: commons-csv Updated Branches: refs/heads/CSV-216 c290f133c -> 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 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; + } }