@@ -36,8 +36,11 @@ public class CSVRecord implements Serializable, Iterable<String> {
3636
3737 private final long characterPosition ;
3838
39- /** The accumulated comments (if any) */
40- private final String comment ;
39+ /** The accumulated comments (if any)
40+ *
41+ * package-private so it can be mutated by {@link CSVMutableRecord}
42+ */
43+ String comment ;
4144
4245 /** The column name to index mapping. */
4346 private final Map <String , Integer > mapping ;
@@ -181,6 +184,28 @@ public boolean hasComment() {
181184 return comment != null ;
182185 }
183186
187+ /**
188+ * Return an immutable CSVRecord.
189+ * <p>
190+ * Immutable records have fixed values and are thus thread-safe.
191+ * <p>
192+ * If this record is already immutable, it will be returned directly,
193+ * otherwise a copy of its current values will be made.
194+ * <p>
195+ * Use {@link #mutable()} or {@link #withValue(int, String)} to get a mutable CSVRecord.
196+ *
197+ * @return Am immutable CSVRecord
198+ */
199+ public CSVRecord immutable () {
200+ if (isMutable ()) {
201+ // Subclass is probably CSVMutableRecord, freeze values
202+ String [] frozenValue = Arrays .copyOf (values , values .length );
203+ return new CSVRecord (frozenValue , mapping , comment , recordNumber , characterPosition );
204+ } else {
205+ return this ;
206+ }
207+ }
208+
184209 /**
185210 * Checks whether a given column is mapped, i.e. its name has been defined to the parser.
186211 *
@@ -191,7 +216,11 @@ public boolean hasComment() {
191216 public boolean isMapped (final String name ) {
192217 return mapping != null && mapping .containsKey (name );
193218 }
194-
219+
220+ boolean isMutable () {
221+ return false ;
222+ }
223+
195224 /**
196225 * Checks whether a given columns is mapped and has a value.
197226 *
@@ -212,6 +241,28 @@ public boolean isSet(final String name) {
212241 public Iterator <String > iterator () {
213242 return toList ().iterator ();
214243 }
244+
245+ /**
246+ * Return a mutable CSVRecord.
247+ * <p>
248+ * Mutable records have more efficient implementations of
249+ * {@link #withValue(int, String)} and {@link #withValue(String, String)}
250+ * for when multiple modifications are to be done on the same record.
251+ * <p>
252+ * If this record is already mutable, it will be returned directly, otherwise
253+ * a copy of its values will be made for the new mutable record.
254+ * <p>
255+ * Use {@link #immutable()} to freeze a mutable CSVRecord.
256+ *
257+ * @return A mutable CSVRecord
258+ */
259+ public CSVRecord mutable () {
260+ if (isMutable ()) {
261+ return this ;
262+ }
263+ String [] newValues = Arrays .copyOf (values , values .length );
264+ return new CSVMutableRecord (newValues , mapping , comment , recordNumber , characterPosition );
265+ }
215266
216267 void put (final int index , String value ) {
217268 values [index ] = value ;
@@ -286,5 +337,52 @@ public String toString() {
286337 String [] values () {
287338 return values ;
288339 }
340+
341+ /**
342+ * Return a CSVRecord with the given column value set.
343+ *
344+ * @param name
345+ * the name of the column to set.
346+ * @param value
347+ * The new value to set
348+ * @throws IllegalStateException
349+ * if no header mapping was provided
350+ * @throws IllegalArgumentException
351+ * if {@code name} is not mapped or if the record is inconsistent
352+ * @return A mutated CSVRecord
353+ */
354+ public CSVRecord withValue (String name , String value ) {
355+ CSVRecord r = mutable ();
356+ r .put (name , value );
357+ return r ;
358+ }
359+
360+ /**
361+ * Return a CSVRecord with the given column value set.
362+ *
363+ * @param index
364+ * the column to be retrieved.
365+ * @param value
366+ * The new value to set
367+ * @return A mutated CSVRecord
368+ */
369+ public CSVRecord withValue (int index , String value ) {
370+ CSVRecord r = mutable ();
371+ r .put (index , value );
372+ return r ;
373+ }
374+
375+ /**
376+ * Return a CSVRecord with the given comment set.
377+ *
378+ * @param comment
379+ * the comment to set, or <code>null</code> for no comment.
380+ * @return A mutated CSVRecord
381+ */
382+ public CSVRecord withComment (String comment ) {
383+ CSVRecord r = mutable ();
384+ r .comment = comment ;
385+ return r ;
386+ }
289387
290388}
0 commit comments