diff --git a/src/main/java/org/writer/Csv.java b/src/main/java/org/writer/Csv.java new file mode 100644 index 0000000..c09e46e --- /dev/null +++ b/src/main/java/org/writer/Csv.java @@ -0,0 +1,20 @@ +package org.writer; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Аннотация для помечания полей, + * которые необходимо сохранять в + * CSV файл + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Csv { + /** + * Имя колонки в CSV файле + */ + String name() default ""; +} diff --git a/src/main/java/org/writer/Main.java b/src/main/java/org/writer/Main.java index 40e8213..5df8aa1 100644 --- a/src/main/java/org/writer/Main.java +++ b/src/main/java/org/writer/Main.java @@ -1,7 +1,27 @@ package org.writer; +import org.writer.model.Months; +import org.writer.model.Person; +import org.writer.model.Student; + +import java.util.List; + public class Main { public static void main(String[] args) { - System.out.println("Hello world!"); + Writable writable = new WritableImpl(); + + List students = List.of( + new Student("Nick", List.of("5,4,3,3,4")), + new Student("Paul", List.of("4,4,4,4,4")), + new Student("Ann", List.of("5,5,5,5,5")) + ); + + List persons = List.of( + new Person("John", "Doe", 1, Months.JANUARY, 1991), + new Person("Alexandr", "Pushkin", 6, Months.JUNE, 1799) + ); + + writable.writeToFile(students, "students.csv"); + writable.writeToFile(persons, "persons.csv"); } } \ No newline at end of file diff --git a/src/main/java/org/writer/WritableImpl.java b/src/main/java/org/writer/WritableImpl.java new file mode 100644 index 0000000..622b732 --- /dev/null +++ b/src/main/java/org/writer/WritableImpl.java @@ -0,0 +1,67 @@ +package org.writer; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Класс, предназанченный для записи коллекции объектов в CSV-файл + */ +public class WritableImpl implements Writable { + + /** + * Метод, для записи коллекуии в файл формата CSV + * + * @param data - коллекция объектов для сохранения + * @param fileName - имя файла, в который будут сохранены данные + */ + @Override + public void writeToFile(List data, String fileName) { + if (data == null || data.isEmpty()) { + throw new IllegalArgumentException("data is null or empty"); + } + + Class clazz = data.get(0).getClass(); + List fields = fieldsToCsv(clazz); + + try ( + BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName)) + ) { + fileWriter.write( + fields.stream() + .map(f -> f.getAnnotation(Csv.class).name()) + .collect(Collectors.joining(","))); + + fileWriter.newLine(); + + for (Object o : data) { + List values = new ArrayList<>(); + for (Field f : o.getClass().getDeclaredFields()) { + if (f.isAnnotationPresent(Csv.class)) { + f.setAccessible(true); + Object val = f.get(o); + if (val != null) { + values.add(val.toString()); + } + } + } + fileWriter.write(String.join(",", values)); + fileWriter.newLine(); + } + + } catch (IOException | IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } + + private List fieldsToCsv(Class clazz) { + return Arrays.stream(clazz.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Csv.class)) + .toList(); + } +} diff --git a/src/main/java/org/writer/model/Person.java b/src/main/java/org/writer/model/Person.java index ba8576b..deccb12 100644 --- a/src/main/java/org/writer/model/Person.java +++ b/src/main/java/org/writer/model/Person.java @@ -3,6 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import org.writer.Csv; @Data @Builder @@ -10,13 +11,16 @@ public class Person { private String firstName; - + @Csv(name = "lastName") private String lastName; + @Csv(name = "dayOfBirth") private int dayOfBirth; + @Csv(name = "monthOfBirth") private Months monthOfBirth; + @Csv(name = "yearOfBirth") private int yearOfBirth; } diff --git a/src/main/java/org/writer/model/Student.java b/src/main/java/org/writer/model/Student.java index 2b549c4..4ae6407 100644 --- a/src/main/java/org/writer/model/Student.java +++ b/src/main/java/org/writer/model/Student.java @@ -3,6 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import org.writer.Csv; import java.util.List; @@ -11,7 +12,9 @@ @AllArgsConstructor public class Student { + @Csv(name = "name") private String name; + @Csv(name = "score") private List score; } \ No newline at end of file diff --git a/src/test/java/org/writer/WritableImplTest.java b/src/test/java/org/writer/WritableImplTest.java new file mode 100644 index 0000000..332d78f --- /dev/null +++ b/src/test/java/org/writer/WritableImplTest.java @@ -0,0 +1,65 @@ +package org.writer; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class WritableImplTest { + private final Writable writable = new WritableImpl(); + + static class TestData{ + @Csv(name = "name") + private final String name; + @Csv(name = "age") + private final int age; + + private byte ignoredData; + + public TestData(String name, int age){ + this.name = name; + this.age = age; + } + } + + @Test + void testWriteWithNullData() { + + assertThrows(IllegalArgumentException.class, + () -> writable.writeToFile(null, "some.csv")); + + } + + @Test + void testWriteWithEmptyData() { + + assertThrows(IllegalArgumentException.class, + () -> writable.writeToFile(new ArrayList<>(), "some.csv")); + + } + + @Test + void testWriteSuccess() throws IOException { + String fileName = "some.csv"; + List testData = new ArrayList<>(); + testData.add(new TestData("name1", 1)); + testData.add(new TestData("name2", 2)); + testData.add(new TestData("name3", 3)); + + writable.writeToFile(testData, fileName); + + List lines = Files.readAllLines(Path.of(fileName)); + + assertEquals(4, lines.size()); + assertEquals("name,age", lines.get(0)); + assertEquals("name1,1", lines.get(1)); + assertEquals("name2,2", lines.get(2)); + assertEquals("name3,3", lines.get(3)); + } +} \ No newline at end of file