The writer automatically generates a CSV header based on + * the object's fields and ensures header consistency when appending data.
+ * + *This class is not thread-safe.
+ */ +public class CsvFileWriter implements Writable { + private PipelineAll objects in the list must be of the same type. The CSV header + * is generated automatically using reflection.
+ * + * @param data list of objects to be written; must not be empty and must contain + * objects of the same type + * @param fileName name of the target CSV file + * @throws ArrayIsEmptyException if the data list is empty + * @throws IllegalArgumentException if the list contains objects of different types + * @throws IllegalStateException if an existing CSV header does not match + */ + @Override + public void writeToFile(List> data, String fileName) { + this.csvContext = new CsvContext(data, fileName); + this.writeToCsvFilePipeline = buildPipeline(); + writeToCsvFilePipeline.execute(csvContext); + } + + + private PipelineThe method appends the row followed by a line separator.
+ * + * @param writer the {@link BufferedWriter} used to write data to the CSV file + * @param csvRow the CSV-formatted row to write + * @throws RuntimeException if an I/O error occurs while writing the row + */ + private void writeCsvRow(BufferedWriter writer, String csvRow) { + try { + writer.write(csvRow); + writer.newLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Escapes a value according to CSV format rules. + * + *If the value contains a comma, double quote, or line break, + * it is wrapped in double quotes and internal quotes are escaped + * by doubling them.
+ * + * @param value the raw value to escape + * @return a CSV-safe representation of the value + */ + private String escapeCsv(String value) { + + if (value.contains(",") || value.contains("\"") || value.contains("\n")) { + value = value.replace("\"", "\"\""); + return "\"" + value + "\""; + } + return value; + } +} diff --git a/src/main/java/org/writer/exception/ArrayIsEmptyException.java b/src/main/java/org/writer/exception/ArrayIsEmptyException.java new file mode 100644 index 0000000..7c01890 --- /dev/null +++ b/src/main/java/org/writer/exception/ArrayIsEmptyException.java @@ -0,0 +1,6 @@ +package org.writer.exception; + +public class ArrayIsEmptyException extends RuntimeException { + public ArrayIsEmptyException(String s) { + } +} diff --git a/src/main/java/org/writer/exception/CsvHeaderMismatchException.java b/src/main/java/org/writer/exception/CsvHeaderMismatchException.java new file mode 100644 index 0000000..47b79e6 --- /dev/null +++ b/src/main/java/org/writer/exception/CsvHeaderMismatchException.java @@ -0,0 +1,6 @@ +package org.writer.exception; + +public class CsvHeaderMismatchException extends RuntimeException { + public CsvHeaderMismatchException(String s) { + } +} diff --git a/src/main/java/org/writer/exception/CsvWriteException.java b/src/main/java/org/writer/exception/CsvWriteException.java new file mode 100644 index 0000000..232b80c --- /dev/null +++ b/src/main/java/org/writer/exception/CsvWriteException.java @@ -0,0 +1,8 @@ +package org.writer.exception; + +import java.io.IOException; + +public class CsvWriteException extends RuntimeException { + public CsvWriteException(String failedToWriteCsvFile, IOException e) { + } +} diff --git a/src/main/java/org/writer/model/Person.java b/src/main/java/org/writer/model/Person.java index ba8576b..9db9959 100644 --- a/src/main/java/org/writer/model/Person.java +++ b/src/main/java/org/writer/model/Person.java @@ -4,6 +4,8 @@ import lombok.Builder; import lombok.Data; +import java.util.List; + @Data @Builder @AllArgsConstructor @@ -19,4 +21,91 @@ public class Person { private int yearOfBirth; + + + public static List