diff --git a/java-oop-ru/code-generation/.gitignore b/java-oop-ru/code-generation/.gitignore new file mode 100644 index 0000000..67bcc2f --- /dev/null +++ b/java-oop-ru/code-generation/.gitignore @@ -0,0 +1,2 @@ +.gradle/ +build/ diff --git a/java-oop-ru/code-generation/Makefile b/java-oop-ru/code-generation/Makefile new file mode 100644 index 0000000..906b551 --- /dev/null +++ b/java-oop-ru/code-generation/Makefile @@ -0,0 +1,5 @@ +test: + gradle test + +example: + java src/main/java/exercise/Example.java diff --git a/java-oop-ru/code-generation/README.html b/java-oop-ru/code-generation/README.html new file mode 100644 index 0000000..de92b5f --- /dev/null +++ b/java-oop-ru/code-generation/README.html @@ -0,0 +1,109 @@ + + + +
+ + + + + + + + \ No newline at end of file diff --git a/java-oop-ru/code-generation/README.md b/java-oop-ru/code-generation/README.md new file mode 100644 index 0000000..6c0c7ba --- /dev/null +++ b/java-oop-ru/code-generation/README.md @@ -0,0 +1,83 @@ +# Генерация кода + +В этом задании вам предстоит поработать с библиотекой Lombok, которая позволяет генерировать код с помощью аннотаций. + +## Ссылки + +* [Проект Lombok](https://projectlombok.org/) +* [Объект DataMapper](https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html) +* [Метод readValue()](https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html#readValue(java.lang.String,%20java.lang.Class)) +* [Метод writeValueAsString()](https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html#writeValueAsString(java.lang.Object)) +* [Класс Files для работы с файлами](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/Files.html) + +## main/java/exercise/User.java + +## Задачи + +* В файле создан класс `User`, который описывает владельца автомобиля. В классе уже определены все свойства, но нет конструктора и геттеров. Допишите нужную аннотацию lombock, чтобы автоматически сгенерировать конструктор и геттеры для всех свойств и сделать класс неизменяемым. + +```java +User owner = new User(1, "Ivan", "P", 25); +// Вызываем автоматически сгенерированный геттер +owner.getFirstName(); // "Ivan" +``` + +## main/java/exercise/Car.java + +## Задачи + +* В файле уже создан класс `Car`, который описывает автомобиль. Допишите нужную аннотацию lombock, чтобы автоматически сгенерировать конструктор и геттеры для всех свойств и сделать класс неизменяемым. + +* Дополнительно создайте в классе два метода: + + * Публичный метод `serialize()` — cериализует объект. Метод возвращает JSON представление объекта (в виде строки). + * Публичный статический метод `unserialize()`, который принимает в качестве аргумента строку (JSON представление объекта класса `Car`) и возвращает объект класса `Car` с соответствующими свойствами. + + ```java + Car car = new Car(1, "bmv", "x5", "black", owner); + String jsonRepresentation = car.serialize(); + System.out.println(jsonRepresentation); // => + /* + { + "id":1, + "brand":"bmv", + "model":"x5", + "color":"black", + "owner":{ + "id":1, + "firstName":"Ivan", + "lastName":"P", + "age":25 + } + } + */ + + String jsonRepresentation = // получаем JSON представление объекта + Car instance = Car.unserialize(jsonRepresentation); + instance.getBrand(); // "bmv" + instance.getModel(); // "x5" + ``` + +## main/java/exercise/App.java + +## Задачи + +* Создайте класс `App` с публичными статическими методами: + + * `save()` — принимает в качестве аргумента путь к файлу (объект класса `Path`) и объект класса `Car`. Метод сохраняет представление объекта в файл по переданному пути. Чтобы сохранить объект в файл, вам нужно будет представить его в виде строки (сериализовать). + + * `extract()` — принимает в качестве аргумента путь к файлу (объект класса `Path`), в котором содержится JSON представление объекта `Car` и возвращает инстанс класса `Car` с соответствующими свойствами. + +```java +Path path1 = Paths.get("/tmp/file1.json"); +Car car1 = new Car(1, "audi", "q3", "black", owner); +App.save(path1, car1); // Сохраняет представление объекта в файл + +Path path2 = Paths.get("/tmp/file2.json"); +Car car2 = App.extract(path2); // Возвращает инстанс класса Car +car2.getModel(); // "passat" +``` + +## Подсказки + +* Для преобразования объекта в JSON строку и обратно, воспользуйтесь классом [ObjectMapper](https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html) diff --git a/java-oop-ru/code-generation/build.gradle b/java-oop-ru/code-generation/build.gradle new file mode 100644 index 0000000..4b10a8a --- /dev/null +++ b/java-oop-ru/code-generation/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'java' + id 'com.adarshr.test-logger' version '2.1.1' +} + +repositories { + mavenCentral() +} + +dependencies { + compileOnly 'org.projectlombok:lombok:1.18.20' + annotationProcessor 'org.projectlombok:lombok:1.18.20' + testCompileOnly 'org.projectlombok:lombok:1.18.20' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.20' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.0-M1' + testImplementation 'org.assertj:assertj-core:3.19.0' + + implementation 'com.fasterxml.jackson.core:jackson-core:2.8.8' + implementation 'com.fasterxml.jackson.core:jackson-annotations:2.8.8' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.8.8' +} + +test { + useJUnitPlatform() +} + +testlogger { + showStandardStreams = true +} + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} diff --git a/java-oop-ru/code-generation/examples/Example.java b/java-oop-ru/code-generation/examples/Example.java new file mode 100644 index 0000000..e8b9b15 --- /dev/null +++ b/java-oop-ru/code-generation/examples/Example.java @@ -0,0 +1,39 @@ +package exercise; + +import exercise.demo.Item; + +class Example { + public static void main(String[] args) { + //data + getter/setter/toString +// Item milk = new Item(); +// milk.setId(1); +// milk.setName("Молоко"); +// milk.setPrice(99.90); +// System.out.println(milk); +//// +// Item bread = new Item(); +// bread.setId(1); +// bread.setName("Хлеб"); +// bread.setPrice(69.90); + +// System.out.println(milk.equals(bread)); + + +// // builder +// Item item = Item.builder() +// .id(1) +// .name("Котлета") +// .price(100.0) +// .build(); +//// +// System.out.println(item); + + // nonNull + Item item = Item.builder() + .price(10.0) + .name("Йогурт") + .id(12) + .build(); + System.out.println(item); + } +} diff --git a/java-oop-ru/code-generation/lombok.config b/java-oop-ru/code-generation/lombok.config new file mode 100644 index 0000000..de90a0e --- /dev/null +++ b/java-oop-ru/code-generation/lombok.config @@ -0,0 +1,2 @@ +lombok.anyConstructor.addConstructorProperties=true +config.stopBubbling = true diff --git a/java-oop-ru/code-generation/presentation.pdf b/java-oop-ru/code-generation/presentation.pdf new file mode 100644 index 0000000..094eff4 Binary files /dev/null and b/java-oop-ru/code-generation/presentation.pdf differ diff --git a/java-oop-ru/code-generation/settings.gradle b/java-oop-ru/code-generation/settings.gradle new file mode 100644 index 0000000..0499e32 --- /dev/null +++ b/java-oop-ru/code-generation/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'code-generation' diff --git a/java-oop-ru/code-generation/src/main/java/exercise/App.java b/java-oop-ru/code-generation/src/main/java/exercise/App.java new file mode 100644 index 0000000..a7917bf --- /dev/null +++ b/java-oop-ru/code-generation/src/main/java/exercise/App.java @@ -0,0 +1,9 @@ +package exercise; + +import java.nio.file.Path; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; + +// BEGIN + +// END diff --git a/java-oop-ru/code-generation/src/main/java/exercise/Car.java b/java-oop-ru/code-generation/src/main/java/exercise/Car.java new file mode 100644 index 0000000..f3a69bc --- /dev/null +++ b/java-oop-ru/code-generation/src/main/java/exercise/Car.java @@ -0,0 +1,19 @@ +package exercise; + +import lombok.Value; +import com.fasterxml.jackson.databind.ObjectMapper; + +// BEGIN + +// END +class Car { + int id; + String brand; + String model; + String color; + User owner; + + // BEGIN + + // END +} diff --git a/java-oop-ru/code-generation/src/main/java/exercise/User.java b/java-oop-ru/code-generation/src/main/java/exercise/User.java new file mode 100644 index 0000000..ab62cea --- /dev/null +++ b/java-oop-ru/code-generation/src/main/java/exercise/User.java @@ -0,0 +1,13 @@ +package exercise; + +import lombok.Value; + +// BEGIN + +// END +class User { + int id; + String firstName; + String lastName; + int age; +} diff --git a/java-oop-ru/code-generation/src/main/java/exercise/demo/Item.java b/java-oop-ru/code-generation/src/main/java/exercise/demo/Item.java new file mode 100644 index 0000000..8588c0e --- /dev/null +++ b/java-oop-ru/code-generation/src/main/java/exercise/demo/Item.java @@ -0,0 +1,12 @@ +package exercise.demo; + +import lombok.Builder; +import lombok.NonNull; + +@Builder +public class Item { + @NonNull + private Integer id; + private String name; + private Double price; +} diff --git a/java-oop-ru/code-generation/src/test/java/exercise/AppTest.java b/java-oop-ru/code-generation/src/test/java/exercise/AppTest.java new file mode 100644 index 0000000..4230252 --- /dev/null +++ b/java-oop-ru/code-generation/src/test/java/exercise/AppTest.java @@ -0,0 +1,71 @@ +package exercise; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.nio.file.Files; +import java.util.Map; +import java.util.HashMap; + + + +class ValidationTest { + + private static ObjectMapper objectMapper; + private static Path tempPath; + + @BeforeAll + static void setUp() throws Exception { + objectMapper = new ObjectMapper(); + } + + @BeforeEach + void createTempFile() throws Exception { + tempPath = Files.createTempFile("temp", ""); + } + + @AfterEach + void deleteTempFile() throws Exception { + Files.deleteIfExists(tempPath); + } + + private static String readFile(Path path) throws Exception { + return Files.readString(path); + } + + private static Path getFixturePath(String fileName) { + return Paths.get("src/test/resources/", fileName).toAbsolutePath().normalize(); + } + + @Test + void testSave() throws Exception { + User owner = new User(1, "Ivan", "Petrov", 25); + Car car = new Car(1, "bmv", "x5", "black", owner); + App.save(tempPath, car); + String actualContent = readFile(tempPath); + Map