From 4188cd8e8168277a699f7183d7f654c27c15ef3b Mon Sep 17 00:00:00 2001 From: Ivan Zinchenko Date: Sun, 31 Mar 2024 15:53:10 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B8=20=D0=B8=D1=85=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- db.xml | 2 +- db.xml.example | 117 ++++++++++++++++++ src/main/java/me/zinch/App.java | 15 ++- src/main/java/me/zinch/commands/Add.java | 3 +- src/main/java/me/zinch/commands/Command.java | 11 +- src/main/java/me/zinch/commands/Save.java | 13 +- src/main/java/me/zinch/console/Console.java | 103 ++++++++------- .../exceptions/CommandActionException.java | 15 +++ .../exceptions/DbInitializationException.java | 9 ++ .../IllegalProductDtoException.java | 15 +++ .../zinch/exceptions/ValidationException.java | 13 ++ .../java/me/zinch/files/DbController.java | 19 +-- .../java/me/zinch/models/Coordinates.java | 6 +- src/main/java/me/zinch/models/Location.java | 6 +- src/main/java/me/zinch/models/Person.java | 6 +- src/main/java/me/zinch/models/Product.java | 22 ++-- .../me/zinch/validator/ValidateResult.java | 28 +++++ .../java/me/zinch/validator/Validators.java | 17 +-- .../me/zinch/wrapper/ProductCollection.java | 17 ++- 20 files changed, 329 insertions(+), 112 deletions(-) create mode 100644 db.xml.example create mode 100644 src/main/java/me/zinch/exceptions/CommandActionException.java create mode 100644 src/main/java/me/zinch/exceptions/DbInitializationException.java create mode 100644 src/main/java/me/zinch/exceptions/IllegalProductDtoException.java create mode 100644 src/main/java/me/zinch/exceptions/ValidationException.java create mode 100644 src/main/java/me/zinch/validator/ValidateResult.java diff --git a/.gitignore b/.gitignore index 60fba23..1771f2c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,4 @@ bin/ .DS_Store ### Build ### -target - -.db.xml.bak \ No newline at end of file +target \ No newline at end of file diff --git a/db.xml b/db.xml index fe38691..d920776 100644 --- a/db.xml +++ b/db.xml @@ -1 +1 @@ -1Product 1100501709294400.00000000050PN12330KILOGRAMSJohn DoeAB12345BLACK10.520Home2Product 22001001709294700.00000000080PN45660CENTIMETERSAlice SmithCD67890BLUE20.830Office3Product 3150-2001709295000.00000000012090GRAMSEmma JohnsonEF24680GREEN30.240Warehouse5Product 54004001709295600.000000000150PN246100CENTIMETERSGrace LeeIJ35791WHITE50.960Store \ No newline at end of file +341Product A1000-5001711875600.0000000001part11000KILOGRAMSJohn Doe1234GREEN55.5Home \ No newline at end of file diff --git a/db.xml.example b/db.xml.example new file mode 100644 index 0000000..3885e88 --- /dev/null +++ b/db.xml.example @@ -0,0 +1,117 @@ + + + + 1 + Product 1 + + 100 + 50 + + 2024-03-01T12:00:00Z + 50 + PN123 + 30 + KILOGRAMS + + John Doe + AB12345 + BLACK + + 10.5 + 20 + Home + + + + + 2 + Product 2 + + 200 + 100 + + 2024-03-01T12:05:00Z + 80 + PN456 + 60 + CENTIMETERS + + Alice Smith + CD67890 + BLUE + + 20.8 + 30 + Office + + + + + 3 + Product 3 + + 150 + -200 + + 2024-03-01T12:10:00Z + 120 + 90 + GRAMS + + Emma Johnson + EF24680 + GREEN + + 30.2 + 40 + Warehouse + + + + + 4 + Product 4 + + 300 + -300 + + 2024-03-01T12:15:00Z + 200 + PN789 + 150 + KILOGRAMS + + Bob Brown + GH13579 + ORANGE + + 40.6 + 50 + Factory + + + + + 5 + Product 5 + + 400 + 400 + + 2024-03-01T12:20:00Z + 150 + PN246 + 100 + CENTIMETERS + + Grace Lee + IJ35791 + WHITE + + 50.9 + 60 + Store + + + + \ No newline at end of file diff --git a/src/main/java/me/zinch/App.java b/src/main/java/me/zinch/App.java index 760e856..8b94c36 100644 --- a/src/main/java/me/zinch/App.java +++ b/src/main/java/me/zinch/App.java @@ -1,12 +1,19 @@ package me.zinch; import me.zinch.console.Console; -import me.zinch.files.DbController; -import me.zinch.wrapper.ProductCollection; +import me.zinch.exceptions.ValidationException; + +import java.io.IOException; public class App { public static void main(String[] args) { - ProductCollection productCollection = new ProductCollection(DbController.loadDb()); - Console.run(productCollection); + try { + Console.run(); + } catch (ValidationException e) { + System.out.println("Ошибка при валидации БД. Некоторые данные не валидны."); + System.out.println(e.getMessage()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } } } diff --git a/src/main/java/me/zinch/commands/Add.java b/src/main/java/me/zinch/commands/Add.java index ff91db1..2a866bf 100644 --- a/src/main/java/me/zinch/commands/Add.java +++ b/src/main/java/me/zinch/commands/Add.java @@ -1,6 +1,7 @@ package me.zinch.commands; import me.zinch.console.Console; +import me.zinch.exceptions.CommandActionException; import me.zinch.wrapper.ProductCollection; import java.util.regex.Pattern; @@ -11,7 +12,7 @@ public class Add extends Command { } @Override - public void action(ProductCollection productCollection) { + public void action(ProductCollection productCollection) throws CommandActionException { var productDTO = Console.readProductDTO(); var product = productCollection.addProduct(productDTO); System.out.format("Продукт %s был добавлен под id %d", product.getName(), product.getId()); diff --git a/src/main/java/me/zinch/commands/Command.java b/src/main/java/me/zinch/commands/Command.java index 14e37a3..b73b95d 100644 --- a/src/main/java/me/zinch/commands/Command.java +++ b/src/main/java/me/zinch/commands/Command.java @@ -1,5 +1,6 @@ package me.zinch.commands; +import me.zinch.exceptions.CommandActionException; import me.zinch.wrapper.ProductCollection; import java.util.regex.Pattern; @@ -21,21 +22,21 @@ public abstract class Command { this.pattern = Pattern.compile("^" + name); } - public String getName() { + public final String getName() { return name; } - public String getDescription() { + public final String getDescription() { return description; } - public Pattern getPattern() { + public final Pattern getPattern() { return pattern; } - public boolean checkPattern(String input) { + public final boolean checkPattern(String input) { return pattern.matcher(input).matches(); } - public abstract void action(ProductCollection productCollection); + public abstract void action(ProductCollection productCollection) throws CommandActionException; } diff --git a/src/main/java/me/zinch/commands/Save.java b/src/main/java/me/zinch/commands/Save.java index 23537da..0ec205b 100644 --- a/src/main/java/me/zinch/commands/Save.java +++ b/src/main/java/me/zinch/commands/Save.java @@ -1,16 +1,23 @@ package me.zinch.commands; +import me.zinch.exceptions.CommandActionException; import me.zinch.files.DbController; import me.zinch.wrapper.ProductCollection; +import java.io.IOException; + public class Save extends Command { public Save() { super("save", "сохранить коллекцию в файл"); } @Override - public void action(ProductCollection productCollection) { - DbController.saveDb(productCollection.toList()); - System.out.println("Коллекция была сохранена"); + public void action(ProductCollection productCollection) throws CommandActionException { + try { + DbController.saveDb(productCollection.toList()); + System.out.println("Коллекция была сохранена"); + } catch (IOException e) { + throw new CommandActionException(e.getMessage()); + } } } diff --git a/src/main/java/me/zinch/console/Console.java b/src/main/java/me/zinch/console/Console.java index beae45d..4602ce4 100644 --- a/src/main/java/me/zinch/console/Console.java +++ b/src/main/java/me/zinch/console/Console.java @@ -1,6 +1,9 @@ package me.zinch.console; import me.zinch.commands.CommandManager; +import me.zinch.exceptions.CommandActionException; +import me.zinch.exceptions.IllegalProductDtoException; +import me.zinch.files.DbController; import me.zinch.models.Color; import me.zinch.models.Coordinates; import me.zinch.models.Location; @@ -9,6 +12,7 @@ import me.zinch.models.ProductDTO; import me.zinch.models.UnitOfMeasure; import me.zinch.wrapper.ProductCollection; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; @@ -18,8 +22,6 @@ public class Console { private static boolean isRunning = true; private static final List history = new ArrayList<>(); - private Console() {} - private static void appendHistory(String input) { history.add(input); } @@ -32,63 +34,68 @@ public class Console { return history.get(history.size() - 1); } - public static ProductDTO readProductDTO() { - var productDTO = new ProductDTO(); - System.out.println("Заполните следующие поля: "); - System.out.print("Название: "); - productDTO.setName(scanner.nextLine().trim()); - - System.out.print("Координата x: "); - long x = Long.parseLong(scanner.nextLine().trim()); - System.out.print("Координата y: "); - long y = Long.parseLong(scanner.nextLine().trim()); - productDTO.setCoordinates(new Coordinates(x, y)); - - System.out.print("Цена: "); - productDTO.setPrice(Long.parseLong(scanner.nextLine().trim())); - System.out.print("Номер части: "); - productDTO.setPartNumber(scanner.nextLine().trim()); - System.out.print("Себестоимость: "); - productDTO.setManufactureCost(Long.parseLong(scanner.nextLine().trim())); - System.out.print("Единица измерения(Килограммы[0], Сантиметры[1], Граммы[2]): "); + public static ProductDTO readProductDTO() throws IllegalProductDtoException { try { - productDTO.setUnitOfMeasure(UnitOfMeasure.create(Integer.parseInt(scanner.nextLine().trim()))); + var productDTO = new ProductDTO(); + System.out.println("Заполните следующие поля: "); + System.out.print("Название: "); + productDTO.setName(scanner.nextLine().trim()); + System.out.print("Координата x: "); + long x = Long.parseLong(scanner.nextLine().trim()); + System.out.print("Координата y: "); + long y = Long.parseLong(scanner.nextLine().trim()); + productDTO.setCoordinates(new Coordinates(x, y)); + System.out.print("Цена: "); + productDTO.setPrice(Long.parseLong(scanner.nextLine().trim())); + System.out.print("Номер части: "); + productDTO.setPartNumber(scanner.nextLine().trim()); + System.out.print("Себестоимость: "); + productDTO.setManufactureCost(Long.parseLong(scanner.nextLine().trim())); + System.out.print("Единица измерения(Килограммы[0], Сантиметры[1], Граммы[2]): "); + try { + productDTO.setUnitOfMeasure(UnitOfMeasure.create(Integer.parseInt(scanner.nextLine().trim()))); + } catch (NumberFormatException e) { + productDTO.setUnitOfMeasure(UnitOfMeasure.create(scanner.nextLine().trim())); + } + System.out.print("Имя владельца: "); + var ownerName = scanner.nextLine().trim(); + System.out.print("Данные паспорта: "); + var passportId = scanner.nextLine().trim(); + System.out.print("Цвет волос(Зелёный[0], Чёрный[1], Синий[2], Оранжевый[3], Белый[4]): "); + Color color; + try { + color = Color.create(Integer.parseInt(scanner.nextLine().trim())); + } catch (NumberFormatException e) { + color = Color.create(scanner.nextLine().trim()); + } + System.out.print("Координата x локации: "); + var locationX = Float.parseFloat(scanner.nextLine().trim()); + System.out.print("Координата y локации: "); + var locationY = Integer.parseInt(scanner.nextLine().trim()); + System.out.print("Название: "); + var locationName = scanner.nextLine().trim(); + + productDTO.setOwner(new Person(ownerName, passportId, color, new Location(locationX, locationY, locationName))); + return productDTO; } catch (NumberFormatException e) { - productDTO.setUnitOfMeasure(UnitOfMeasure.create(scanner.nextLine().trim())); + throw new IllegalProductDtoException(); } - - System.out.print("Имя владельца: "); - var ownerName = scanner.nextLine().trim(); - System.out.print("Данные паспорта: "); - var passportId = scanner.nextLine().trim(); - System.out.print("Цвет волос(Зелёный[0], Чёрный[1], Синий[2], Оранжевый[3], Белый[4]): "); - Color color; - try { - color = Color.create(Integer.parseInt(scanner.nextLine().trim())); - } catch (NumberFormatException e) { - color = Color.create(scanner.nextLine().trim()); - } - - System.out.print("Координата x локации: "); - var locationX = Float.parseFloat(scanner.nextLine().trim()); - System.out.print("Координата y локации: "); - var locationY = Integer.parseInt(scanner.nextLine().trim()); - System.out.print("Название: "); - var locationName = scanner.nextLine().trim(); - - productDTO.setOwner(new Person(ownerName, passportId, color, new Location(locationX, locationY, locationName))); - - return productDTO; } - public static void run(ProductCollection productCollection) { + public static void run() throws IOException { + var productCollection = new ProductCollection(DbController.loadDb()); + System.out.println("Добро пожаловать! Для просмотра команд введите help"); while(isRunning) { System.out.print(":"); var input = scanner.nextLine().trim(); var command = CommandManager.getCommandByInput(input); if (command.isPresent()) { appendHistory(input); - command.get().action(productCollection); + try { + command.get().action(productCollection); + } catch (CommandActionException e) { + System.out.println(e.getMessage()); + } } else { System.out.println("Такой команды не существует. Напишите help, чтобы посмотреть список доступных команд."); } diff --git a/src/main/java/me/zinch/exceptions/CommandActionException.java b/src/main/java/me/zinch/exceptions/CommandActionException.java new file mode 100644 index 0000000..9b780fb --- /dev/null +++ b/src/main/java/me/zinch/exceptions/CommandActionException.java @@ -0,0 +1,15 @@ +package me.zinch.exceptions; + +public class CommandActionException extends RuntimeException { + public CommandActionException() { + super("Ошибка во время выполнения команды"); + } + + public CommandActionException(String message) { + super(message); + } + + public CommandActionException(Throwable e) { + super(e); + } +} diff --git a/src/main/java/me/zinch/exceptions/DbInitializationException.java b/src/main/java/me/zinch/exceptions/DbInitializationException.java new file mode 100644 index 0000000..1351143 --- /dev/null +++ b/src/main/java/me/zinch/exceptions/DbInitializationException.java @@ -0,0 +1,9 @@ +package me.zinch.exceptions; + +import java.io.IOException; + +public class DbInitializationException extends IOException { + public DbInitializationException() { + super("Ошибка! Не удалось инициализировать БД. Проверьте, что структура БД верна."); + } +} diff --git a/src/main/java/me/zinch/exceptions/IllegalProductDtoException.java b/src/main/java/me/zinch/exceptions/IllegalProductDtoException.java new file mode 100644 index 0000000..e1c780a --- /dev/null +++ b/src/main/java/me/zinch/exceptions/IllegalProductDtoException.java @@ -0,0 +1,15 @@ +package me.zinch.exceptions; + +public class IllegalProductDtoException extends CommandActionException { + public IllegalProductDtoException() { + super("Ошибка при создании или изменении продукта. Были введены некорректные значения."); + } + + public IllegalProductDtoException(String message) { + super(message); + } + + public IllegalProductDtoException(Throwable e) { + super(e); + } +} diff --git a/src/main/java/me/zinch/exceptions/ValidationException.java b/src/main/java/me/zinch/exceptions/ValidationException.java new file mode 100644 index 0000000..00b6ab9 --- /dev/null +++ b/src/main/java/me/zinch/exceptions/ValidationException.java @@ -0,0 +1,13 @@ +package me.zinch.exceptions; + +public class ValidationException extends jakarta.validation.ValidationException { + public ValidationException() {} + + public ValidationException(String message) { + super(message); + } + + public ValidationException(Throwable e) { + super(e); + } +} diff --git a/src/main/java/me/zinch/files/DbController.java b/src/main/java/me/zinch/files/DbController.java index 4cad167..ef46f98 100644 --- a/src/main/java/me/zinch/files/DbController.java +++ b/src/main/java/me/zinch/files/DbController.java @@ -1,10 +1,12 @@ package me.zinch.files; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DatabindException; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import me.zinch.exceptions.DbInitializationException; import me.zinch.models.Product; import java.io.BufferedInputStream; @@ -26,7 +28,7 @@ public class DbController { xmlMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL); } - public static class Products { + private static class Products { @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "Product") private List products; @@ -42,27 +44,28 @@ public class DbController { } } - public static List loadDb() { + public static List loadDb() throws IOException { try { BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(path)); Products collection = xmlMapper.readValue(bufferedInputStream, Products.class); return collection.getProducts(); } catch (FileNotFoundException e) { - System.err.println("Ошибка! Файл не найден."); + throw new FileNotFoundException("Не удалось найти файл " + path); + } catch (DatabindException e) { + throw new DbInitializationException(); } catch (IOException e) { - System.err.println("Произошла неожиданная ошибка во время работы с файлом!"); + throw new IOException("Произошла неожиданная ошибка во время работы с файлом!"); } - return List.of(); } - public static void saveDb(List list) { + public static void saveDb(List list) throws IOException { try { OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(path)); xmlMapper.writeValue(outputStreamWriter, new Products(list)); } catch (FileNotFoundException e) { - System.err.println("Ошибка! Файл не найден"); + throw new FileNotFoundException(e.getMessage()); } catch (IOException e) { - System.err.println(e.getMessage()); + throw new IOException(e); } } } diff --git a/src/main/java/me/zinch/models/Coordinates.java b/src/main/java/me/zinch/models/Coordinates.java index 52eae4f..16c3b6c 100644 --- a/src/main/java/me/zinch/models/Coordinates.java +++ b/src/main/java/me/zinch/models/Coordinates.java @@ -8,12 +8,12 @@ import jakarta.validation.constraints.NotNull; import java.util.Objects; public class Coordinates { - @Max(value = 883, message = "Максимальное значение поля x: 883") + @Max(value = 883, message = "Coordinates: Максимальное значение координаты x: 883") @JsonProperty("x") private long x; //Максимальное значение поля: 883 - @NotNull(message = "Поле не может быть null") - @Min(value = -427, message = "Значение поля y должно быть больше -427") + @NotNull(message = "Coordinates: Поле не может быть null") + @Min(value = -427, message = "Значение координаты y должно быть больше -427") @JsonProperty("y") private Long y; //Значение поля должно быть больше -427, Поле не может быть null diff --git a/src/main/java/me/zinch/models/Location.java b/src/main/java/me/zinch/models/Location.java index b550135..d2f2ae4 100644 --- a/src/main/java/me/zinch/models/Location.java +++ b/src/main/java/me/zinch/models/Location.java @@ -1,8 +1,8 @@ package me.zinch.models; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import me.zinch.validator.NotEmpty; import java.util.Objects; @@ -10,11 +10,11 @@ public class Location { @JsonProperty("x") private float x; - @NotNull(message = "Поле y не может быть null") + @NotNull(message = "Location: Координата y не может быть null") @JsonProperty("y") private Integer y; //Поле не может быть null - @NotBlank(message = "Строка name не может быть пустой или null") + @NotEmpty(message = "Location: Название локации не может быть пустым или null") @JsonProperty("name") private String name; //Строка не может быть пустой, Поле может быть null diff --git a/src/main/java/me/zinch/models/Person.java b/src/main/java/me/zinch/models/Person.java index 3634b89..8e55e34 100644 --- a/src/main/java/me/zinch/models/Person.java +++ b/src/main/java/me/zinch/models/Person.java @@ -8,20 +8,18 @@ import jakarta.validation.constraints.Size; import java.util.Objects; public class Person { - @NotBlank(message = "Строка name не может быть пустой или null") + @NotBlank(message = "Person: Имя персоны не может быть пустым или null") @JsonProperty("name") private String name; //Поле не может быть null, Строка не может быть пустой - @NotNull(message = "Поле passportID не может быть null") + @NotNull(message = "Person: Поле passportID не может быть null") @Size(min = 5, max = 22, message = "Длина строки passportID должна быть не меньше 5 и не должна быть больше 22") @JsonProperty("passportID") private String passportID; //Длина строки должна быть не меньше 5, Длина строки не должна быть больше 22, Поле не может быть null - @NotNull(message = "Поле hairColor может быть null") @JsonProperty("hairColor") private Color hairColor; //Поле может быть null - @NotNull(message = "Поле location может быть null") @JsonProperty("location") private Location location; //Поле может быть null diff --git a/src/main/java/me/zinch/models/Product.java b/src/main/java/me/zinch/models/Product.java index 7b09cd8..48d6fa0 100644 --- a/src/main/java/me/zinch/models/Product.java +++ b/src/main/java/me/zinch/models/Product.java @@ -11,41 +11,41 @@ import java.time.ZonedDateTime; import java.util.Objects; public class Product { - @NotNull(message = "Поле id не может быть null") - @Min(value = 1, message = "Значение поля id должно быть больше 0") + @NotNull(message = "Product: Поле id не может быть null") + @Min(value = 1, message = "Product: Значение поля id должно быть больше 0") @JsonProperty("id") private Long id; //Поле не может быть null, Значение поля должно быть больше 0, Значение этого поля должно быть уникальным, Значение этого поля должно генерироваться автоматически - @NotBlank(message = "Строка name не может быть пустой или null") + @NotBlank(message = "Product: Строка name не может быть пустой или null") @JsonProperty("name") private String name; //Поле не может быть null, Строка не может быть пустой - @NotNull(message = "Поле coordinates не может быть null ") + @NotNull(message = "Product: Поле coordinates не может быть null ") @JsonProperty("coordinates") private Coordinates coordinates; //Поле не может быть null - @NotNull(message = "Поле creationDate не может быть null") + @NotNull(message = "Product: Поле creationDate не может быть null") @JsonProperty("creationDate") private ZonedDateTime creationDate; //Поле не может быть null, Значение этого поля должно генерироваться автоматически - @NotNull(message = "Поле price не может быть null") - @Min(value = 1, message = "Поле price не может быть null") + @NotNull(message = "Product: Поле price не может быть null") + @Min(value = 1, message = "Product: Значение поля price должно быть больше 0") @JsonProperty("price") private Long price; //Поле не может быть null, Значение поля должно быть больше 0 - @NotEmpty(message = "Строка partNumber не может быть пустой") - @Size(max = 82, message = "Длина строки partNumber не должна быть больше 82") + @NotEmpty(message = "Product: Строка partNumber не может быть пустой") + @Size(max = 82, message = "Product: Длина строки partNumber не должна быть больше 82") @JsonProperty("partNumber") private String partNumber; //Длина строки не должна быть больше 82, Значение этого поля должно быть уникальным, Строка не может быть пустой, Поле может быть null @JsonProperty("manufactureCost") private long manufactureCost; - @NotNull(message = "Поле unitOfMeasure не может быть null") + @NotNull(message = "Product: Поле unitOfMeasure не может быть null") @JsonProperty("unitOfMeasure") private UnitOfMeasure unitOfMeasure; //Поле не может быть null - @NotNull(message = "Поле owner не может быть null") + @NotNull(message = "Product: Поле owner не может быть null") @JsonProperty("owner") private Person owner; //Поле не может быть null diff --git a/src/main/java/me/zinch/validator/ValidateResult.java b/src/main/java/me/zinch/validator/ValidateResult.java new file mode 100644 index 0000000..b103d98 --- /dev/null +++ b/src/main/java/me/zinch/validator/ValidateResult.java @@ -0,0 +1,28 @@ +package me.zinch.validator; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ValidationException; + +import java.util.Set; + +public class ValidateResult { + private final Set> violations; + private final boolean isValid; + + public ValidateResult(Set> violations) { + this.violations = violations; + this.isValid = violations.isEmpty(); + } + + public String getMessage() { + return String.join("\n", violations.stream().map(ConstraintViolation::getMessage).toList()); + } + + public boolean isValid() { + return isValid; + } + + public void throwIfNotValid() throws ValidationException { + if (!isValid) throw new ValidationException(getMessage()); + } +} diff --git a/src/main/java/me/zinch/validator/Validators.java b/src/main/java/me/zinch/validator/Validators.java index 9c29d07..29e719a 100644 --- a/src/main/java/me/zinch/validator/Validators.java +++ b/src/main/java/me/zinch/validator/Validators.java @@ -1,6 +1,5 @@ package me.zinch.validator; -import jakarta.validation.ConstraintViolation; import jakarta.validation.Validation; import jakarta.validation.Validator; import jakarta.validation.ValidatorFactory; @@ -8,7 +7,6 @@ import me.zinch.models.Product; import org.hibernate.validator.HibernateValidator; import java.util.List; -import java.util.Set; public class Validators { private static final Validator validator; @@ -16,22 +14,17 @@ public class Validators { static { ValidatorFactory factory = Validation.byProvider(HibernateValidator.class) .configure() - .showValidatedValuesInTraceLogs(false) + .showValidatedValuesInTraceLogs(true) .buildValidatorFactory(); validator = factory.usingContext().getValidator(); factory.close(); } - public static boolean validateProduct(Product product) { - Set> violations = validator.validate(product); - for (ConstraintViolation violation : violations) { - System.out.println(violation.getMessage()); - } - return violations.isEmpty(); + public static ValidateResult validateProduct(Product product) { + return new ValidateResult<>(validator.validate(product)); } - public static boolean validateProductList(List db) { - // TODO: validate unique ID - return db.stream().allMatch(Validators::validateProduct); + public static List> validateProductList(List db) { + return db.stream().map(Validators::validateProduct).toList(); } } diff --git a/src/main/java/me/zinch/wrapper/ProductCollection.java b/src/main/java/me/zinch/wrapper/ProductCollection.java index c3b9ac4..36da985 100644 --- a/src/main/java/me/zinch/wrapper/ProductCollection.java +++ b/src/main/java/me/zinch/wrapper/ProductCollection.java @@ -1,7 +1,9 @@ package me.zinch.wrapper; +import me.zinch.exceptions.ValidationException; import me.zinch.models.Product; import me.zinch.models.ProductDTO; +import me.zinch.validator.ValidateResult; import me.zinch.validator.Validators; import java.time.Instant; @@ -18,14 +20,14 @@ public class ProductCollection { private final TreeSet productList; private Long idIncrementor; - public ProductCollection(List list) { + public ProductCollection(List list) throws ValidationException { productList = new TreeSet<>(Comparator.comparingLong(Product::getId)); - if (Validators.validateProductList(list)) { - productList.addAll(list); - idIncrementor = productList.last().getId() + 1; - } else { - System.exit(1); + var validationResult = Validators.validateProductList(list); + if (!validationResult.stream().allMatch(ValidateResult::isValid)) { + throw new ValidationException(String.join("\n", validationResult.stream().map(ValidateResult::getMessage).toList())); } + productList.addAll(list); + idIncrementor = productList.last().getId() + 1; } private Long generateId() { @@ -39,18 +41,21 @@ public class ProductCollection { public Product addProduct(ProductDTO productDTO) { var product = productDTO.buildProduct(generateId(), ZonedDateTime.now()); + Validators.validateProduct(product).throwIfNotValid(); productList.add(product); return product; } private Product addProduct(ProductDTO productDTO, Long id, ZonedDateTime creationDate) { var product = productDTO.buildProduct(id, creationDate); + Validators.validateProduct(product).throwIfNotValid(); productList.add(product); return product; } public Product updateProduct(Long id, ProductDTO productDTO) { var product = getProductById(id); + Validators.validateProduct(product).throwIfNotValid(); productList.remove(product); return addProduct(productDTO, product.getId(), product.getCreationDate()); }