Реализована загрузка бд и её валидация
This commit is contained in:
parent
6cc251551b
commit
94ccc698a7
5
.gitignore
vendored
5
.gitignore
vendored
@ -28,4 +28,7 @@ bin/
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
### Build ###
|
||||
target
|
||||
@ -1,3 +0,0 @@
|
||||
Manifest-Version: 1.0
|
||||
Created-By: zinch
|
||||
Main-class: Main
|
||||
6
Makefile
6
Makefile
@ -1,6 +0,0 @@
|
||||
all:
|
||||
rm -rf target
|
||||
javac -d target -sourcepath src src/Main.java src/**/*
|
||||
cd target; jar cfm app.jar ../MANIFEST.mf *.class ./**/*.class
|
||||
mv target/app.jar ./
|
||||
rm -rf target
|
||||
4
Notes.md
Normal file
4
Notes.md
Normal file
@ -0,0 +1,4 @@
|
||||
### Этапы работы программы
|
||||
|
||||
1. Проверка файла с базой данных
|
||||
2. Пользовательский ввод
|
||||
99
README.md
Normal file
99
README.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Лабораторная работа №5
|
||||
|
||||
## Выполнил
|
||||
> ФИ: Зинченко Иван
|
||||
>
|
||||
> ИСУ: 408657
|
||||
>
|
||||
> Вариант: 1632
|
||||
|
||||
## Задание
|
||||
Реализовать консольное приложение, которое реализует управление коллекцией объектов в интерактивном режиме.
|
||||
В коллекции необходимо хранить объекты класса `Product`, описание которого приведено ниже.
|
||||
|
||||
Разработанная программа должна удовлетворять следующим требованиям:
|
||||
- Класс, коллекцией экземпляров которого управляет программа, должен реализовывать сортировку по умолчанию.
|
||||
- Все требования к полям класса (указанные в виде комментариев) должны быть выполнены.
|
||||
- Для хранения необходимо использовать коллекцию типа `java.util.TreeSet`
|
||||
- При запуске приложения коллекция должна автоматически заполняться значениями из файла.
|
||||
- Имя файла должно передаваться программе с помощью: переменная окружения.
|
||||
- Данные должны храниться в файле в формате `xml`
|
||||
- Чтение данных из файла необходимо реализовать с помощью класса `java.io.BufferedInputStream`
|
||||
- Запись данных в файл необходимо реализовать с помощью класса `java.io.OutputStreamWriter`
|
||||
- Все классы в программе должны быть задокументированы в формате javadoc.
|
||||
- Программа должна корректно работать с неправильными данными (ошибки пользовательского ввода, отсутсвие прав доступа к файлу и т.п.).
|
||||
|
||||
В интерактивном режиме программа должна поддерживать выполнение следующих команд:
|
||||
- `help` : вывести справку по доступным командам
|
||||
- `info` : вывести в стандартный поток вывода информацию о коллекции (тип, дата инициализации, количество элементов и т.д.)
|
||||
- `show` : вывести в стандартный поток вывода все элементы коллекции в строковом представлении
|
||||
- `add {element}` : добавить новый элемент в коллекцию
|
||||
- `update id {element}` : обновить значение элемента коллекции, id которого равен заданному
|
||||
- `remove_by_id id` : удалить элемент из коллекции по его id
|
||||
- `clear` : очистить коллекцию
|
||||
- `save` : сохранить коллекцию в файл
|
||||
- `execute_script file_name` : считать и исполнить скрипт из указанного файла. В скрипте содержатся команды в таком же виде, в котором их вводит пользователь в интерактивном режиме.
|
||||
- `exit` : завершить программу (без сохранения в файл)
|
||||
- `add_if_max {element}` : добавить новый элемент в коллекцию, если его значение превышает значение наибольшего элемента этой коллекции
|
||||
- `add_if_min {element}` : добавить новый элемент в коллекцию, если его значение меньше, чем у наименьшего элемента этой коллекции
|
||||
- `remove_lower {element}` : удалить из коллекции все элементы, меньшие, чем заданный
|
||||
- `filter_contains_name name` : вывести элементы, значение поля name которых содержит заданную подстроку
|
||||
- `print_ascending` : вывести элементы коллекции в порядке возрастания
|
||||
- `print_unique_manufacture_cost` : вывести уникальные значения поля manufactureCost всех элементов в коллекции
|
||||
|
||||
Формат ввода команд:
|
||||
- Все аргументы команды, являющиеся стандартными типами данных (примитивные типы, классы-оболочки, String, классы для хранения дат), должны вводиться в той же строке, что и имя команды.
|
||||
- Все составные типы данных (объекты классов, хранящиеся в коллекции) должны вводиться по одному полю в строку.
|
||||
- При вводе составных типов данных пользователю должно показываться приглашение к вводу, содержащее имя поля (например, "Введите дату рождения:")
|
||||
- Если поле является enum'ом, то вводится имя одной из его констант (при этом список констант должен быть предварительно выведен).
|
||||
- При некорректном пользовательском вводе (введена строка, не являющаяся именем константы в enum'е; введена строка вместо числа; введённое число не входит в указанные границы и т.п.) должно быть показано сообщение об ошибке и предложено повторить ввод поля.
|
||||
- Для ввода значений null использовать пустую строку.
|
||||
- Поля с комментарием "Значение этого поля должно генерироваться автоматически" не должны вводиться пользователем вручную при добавлении.
|
||||
|
||||
Описание хранимых в коллекции классов:
|
||||
|
||||
```java
|
||||
public class Product {
|
||||
private Long id; //Поле не может быть null, Значение поля должно быть больше 0, Значение этого поля должно быть уникальным, Значение этого поля должно генерироваться автоматически
|
||||
private String name; //Поле не может быть null, Строка не может быть пустой
|
||||
private Coordinates coordinates; //Поле не может быть null
|
||||
private java.time.ZonedDateTime creationDate; //Поле не может быть null, Значение этого поля должно генерироваться автоматически
|
||||
private Long price; //Поле не может быть null, Значение поля должно быть больше 0
|
||||
private String partNumber; //Длина строки не должна быть больше 82, Значение этого поля должно быть уникальным, Строка не может быть пустой, Поле может быть null
|
||||
private long manufactureCost;
|
||||
private UnitOfMeasure unitOfMeasure; //Поле не может быть null
|
||||
private Person owner; //Поле не может быть null
|
||||
}
|
||||
|
||||
public class Coordinates {
|
||||
private long x; //Максимальное значение поля: 883
|
||||
private Long y; //Значение поля должно быть больше -427, Поле не может быть null
|
||||
}
|
||||
|
||||
public class Person {
|
||||
private String name; //Поле не может быть null, Строка не может быть пустой
|
||||
private String passportID; //Длина строки должна быть не меньше 5, Длина строки не должна быть больше 22, Поле не может быть null
|
||||
private Color hairColor; //Поле может быть null
|
||||
private Location location; //Поле может быть null
|
||||
}
|
||||
|
||||
public class Location {
|
||||
private float x;
|
||||
private Integer y; //Поле не может быть null
|
||||
private String name; //Строка не может быть пустой, Поле может быть null
|
||||
}
|
||||
|
||||
public enum UnitOfMeasure {
|
||||
KILOGRAMS,
|
||||
CENTIMETERS,
|
||||
GRAMS
|
||||
}
|
||||
|
||||
public enum Color {
|
||||
GREEN,
|
||||
BLACK,
|
||||
BLUE,
|
||||
ORANGE,
|
||||
WHITE
|
||||
}
|
||||
```
|
||||
117
db.xml
Normal file
117
db.xml
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Products>
|
||||
<Product>
|
||||
<id>1</id>
|
||||
<name>Product 1</name>
|
||||
<coordinates>
|
||||
<x>100</x>
|
||||
<y>50</y>
|
||||
</coordinates>
|
||||
<creationDate>2024-03-01T12:00:00Z</creationDate>
|
||||
<price>50</price>
|
||||
<partNumber>PN123</partNumber>
|
||||
<manufactureCost>30</manufactureCost>
|
||||
<unitOfMeasure>KILOGRAMS</unitOfMeasure>
|
||||
<owner>
|
||||
<name>John Doe</name>
|
||||
<passportID>AB12345</passportID>
|
||||
<hairColor>BLACK</hairColor>
|
||||
<location>
|
||||
<x>10.5</x>
|
||||
<y>20</y>
|
||||
<name>Home</name>
|
||||
</location>
|
||||
</owner>
|
||||
</Product>
|
||||
<Product>
|
||||
<id>2</id>
|
||||
<name>Product 2</name>
|
||||
<coordinates>
|
||||
<x>200</x>
|
||||
<y>100</y>
|
||||
</coordinates>
|
||||
<creationDate>2024-03-01T12:05:00Z</creationDate>
|
||||
<price>80</price>
|
||||
<partNumber>PN456</partNumber>
|
||||
<manufactureCost>60</manufactureCost>
|
||||
<unitOfMeasure>CENTIMETERS</unitOfMeasure>
|
||||
<owner>
|
||||
<name>Alice Smith</name>
|
||||
<passportID>CD67890</passportID>
|
||||
<hairColor>BLUE</hairColor>
|
||||
<location>
|
||||
<x>20.8</x>
|
||||
<y>30</y>
|
||||
<name>Office</name>
|
||||
</location>
|
||||
</owner>
|
||||
</Product>
|
||||
<Product>
|
||||
<id>3</id>
|
||||
<name>Product 3</name>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>-200</y>
|
||||
</coordinates>
|
||||
<creationDate>2024-03-01T12:10:00Z</creationDate>
|
||||
<price>120</price>
|
||||
<manufactureCost>90</manufactureCost>
|
||||
<unitOfMeasure>GRAMS</unitOfMeasure>
|
||||
<owner>
|
||||
<name>Emma Johnson</name>
|
||||
<passportID>EF24680</passportID>
|
||||
<hairColor>GREEN</hairColor>
|
||||
<location>
|
||||
<x>30.2</x>
|
||||
<y>40</y>
|
||||
<name>Warehouse</name>
|
||||
</location>
|
||||
</owner>
|
||||
</Product>
|
||||
<Product>
|
||||
<id>4</id>
|
||||
<name>Product 4</name>
|
||||
<coordinates>
|
||||
<x>300</x>
|
||||
<y>-300</y>
|
||||
</coordinates>
|
||||
<creationDate>2024-03-01T12:15:00Z</creationDate>
|
||||
<price>200</price>
|
||||
<partNumber>PN789</partNumber>
|
||||
<manufactureCost>150</manufactureCost>
|
||||
<unitOfMeasure>KILOGRAMS</unitOfMeasure>
|
||||
<owner>
|
||||
<name>Bob Brown</name>
|
||||
<passportID>GH13579</passportID>
|
||||
<hairColor>ORANGE</hairColor>
|
||||
<location>
|
||||
<x>40.6</x>
|
||||
<y>50</y>
|
||||
<name>Factory</name>
|
||||
</location>
|
||||
</owner>
|
||||
</Product>
|
||||
<Product>
|
||||
<id>5</id>
|
||||
<name>Product 5</name>
|
||||
<coordinates>
|
||||
<x>400</x>
|
||||
<y>400</y>
|
||||
</coordinates>
|
||||
<creationDate>2024-03-01T12:20:00Z</creationDate>
|
||||
<price>150</price>
|
||||
<partNumber>PN246</partNumber>
|
||||
<manufactureCost>100</manufactureCost>
|
||||
<unitOfMeasure>CENTIMETERS</unitOfMeasure>
|
||||
<owner>
|
||||
<name>Grace Lee</name>
|
||||
<passportID>IJ35791</passportID>
|
||||
<hairColor>WHITE</hairColor>
|
||||
<location>
|
||||
<x>50.9</x>
|
||||
<y>60</y>
|
||||
<name>Store</name>
|
||||
</location>
|
||||
</owner>
|
||||
</Product>
|
||||
</Products>
|
||||
51
pom.xml
Normal file
51
pom.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>me.zinch</groupId>
|
||||
<artifactId>Lab5</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Lab5</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<version>2.15.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.17.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>8.0.1.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>jakarta.el</artifactId>
|
||||
<version>5.0.0-M1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -1,5 +0,0 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
}
|
||||
18
src/main/java/me/zinch/App.java
Normal file
18
src/main/java/me/zinch/App.java
Normal file
@ -0,0 +1,18 @@
|
||||
package me.zinch;
|
||||
|
||||
import me.zinch.files.DbController;
|
||||
import me.zinch.models.Product;
|
||||
import me.zinch.validator.Validators;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class App {
|
||||
public static void main( String[] args ) {
|
||||
List<Product> productList = DbController.loadDb();
|
||||
if (productList != null) {
|
||||
System.out.println(Validators.validateProductList(productList));
|
||||
} else {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/main/java/me/zinch/commands/Command.java
Normal file
29
src/main/java/me/zinch/commands/Command.java
Normal file
@ -0,0 +1,29 @@
|
||||
package me.zinch.commands;
|
||||
|
||||
public abstract class Command {
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String pattern;
|
||||
|
||||
public Command(String name, String description, String pattern) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
public abstract void action();
|
||||
public abstract void action(String param);
|
||||
public abstract void action(String[] params);
|
||||
}
|
||||
41
src/main/java/me/zinch/files/DbController.java
Normal file
41
src/main/java/me/zinch/files/DbController.java
Normal file
@ -0,0 +1,41 @@
|
||||
package me.zinch.files;
|
||||
|
||||
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.models.Product;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DbController {
|
||||
public static class Products {
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
@JacksonXmlProperty(localName = "Product")
|
||||
private List<Product> products;
|
||||
|
||||
public List<Product> getProducts() {
|
||||
return products;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Product> loadDb() {
|
||||
Map<String, String> env = System.getenv();
|
||||
try {
|
||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(env.getOrDefault("DB_FILE", "")));
|
||||
XmlMapper xmlMapper = XmlMapper.builder().addModule(new JavaTimeModule()).build();
|
||||
Products collection = xmlMapper.readValue(bufferedInputStream, Products.class);
|
||||
return collection.getProducts();
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("Ошибка! Файл не найден.");
|
||||
} catch (IOException e) {
|
||||
System.err.println("Произошла неожиданная ошибка во время работы с файлом!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
9
src/main/java/me/zinch/models/Color.java
Normal file
9
src/main/java/me/zinch/models/Color.java
Normal file
@ -0,0 +1,9 @@
|
||||
package me.zinch.models;
|
||||
|
||||
public enum Color {
|
||||
GREEN,
|
||||
BLACK,
|
||||
BLUE,
|
||||
ORANGE,
|
||||
WHITE
|
||||
}
|
||||
40
src/main/java/me/zinch/models/Coordinates.java
Normal file
40
src/main/java/me/zinch/models/Coordinates.java
Normal file
@ -0,0 +1,40 @@
|
||||
package me.zinch.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Coordinates {
|
||||
@Max(value = 883, message = "Максимальное значение поля x: 883")
|
||||
@JsonProperty("x")
|
||||
private long x; //Максимальное значение поля: 883
|
||||
|
||||
@NotNull(message = "Поле не может быть null")
|
||||
@Min(value = -427, message = "Значение поля y должно быть больше -427")
|
||||
@JsonProperty("y")
|
||||
private Long y; //Значение поля должно быть больше -427, Поле не может быть null
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Coordinates{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Coordinates that = (Coordinates) o;
|
||||
return x == that.x && Objects.equals(y, that.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y);
|
||||
}
|
||||
}
|
||||
54
src/main/java/me/zinch/models/Location.java
Normal file
54
src/main/java/me/zinch/models/Location.java
Normal file
@ -0,0 +1,54 @@
|
||||
package me.zinch.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Location {
|
||||
@JsonProperty("x")
|
||||
private float x;
|
||||
|
||||
@NotNull(message = "Поле y не может быть null")
|
||||
@JsonProperty("y")
|
||||
private Integer y; //Поле не может быть null
|
||||
|
||||
@NotBlank(message = "Строка name не может быть пустой или null")
|
||||
@JsonProperty("name")
|
||||
private String name; //Строка не может быть пустой, Поле может быть null
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public Integer getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Location{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Location location = (Location) o;
|
||||
return Float.compare(x, location.x) == 0 && Objects.equals(y, location.y) && Objects.equals(name, location.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, name);
|
||||
}
|
||||
}
|
||||
50
src/main/java/me/zinch/models/Person.java
Normal file
50
src/main/java/me/zinch/models/Person.java
Normal file
@ -0,0 +1,50 @@
|
||||
package me.zinch.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Person {
|
||||
@NotBlank(message = "Строка name не может быть пустой или null")
|
||||
@JsonProperty("name")
|
||||
private String name; //Поле не может быть null, Строка не может быть пустой
|
||||
|
||||
@NotNull(message = "Поле 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
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person{" +
|
||||
"name='" + name + '\'' +
|
||||
", passportID='" + passportID + '\'' +
|
||||
", hairColor=" + hairColor +
|
||||
", location=" + location +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Person person = (Person) o;
|
||||
return Objects.equals(name, person.name) && Objects.equals(passportID, person.passportID) && hairColor == person.hairColor && Objects.equals(location, person.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, passportID, hairColor, location);
|
||||
}
|
||||
}
|
||||
137
src/main/java/me/zinch/models/Product.java
Normal file
137
src/main/java/me/zinch/models/Product.java
Normal file
@ -0,0 +1,137 @@
|
||||
package me.zinch.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import me.zinch.validator.NotEmpty;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Product {
|
||||
@NotNull(message = "Поле id не может быть null")
|
||||
@Min(value = 1, message = "Значение поля id должно быть больше 0")
|
||||
@JsonProperty("id")
|
||||
private Long id; //Поле не может быть null, Значение поля должно быть больше 0, Значение этого поля должно быть уникальным, Значение этого поля должно генерироваться автоматически
|
||||
|
||||
@NotBlank(message = "Строка name не может быть пустой или null")
|
||||
@JsonProperty("name")
|
||||
private String name; //Поле не может быть null, Строка не может быть пустой
|
||||
|
||||
@NotNull(message = "Поле coordinates не может быть null ")
|
||||
@JsonProperty("coordinates")
|
||||
private Coordinates coordinates; //Поле не может быть null
|
||||
|
||||
@NotNull(message = "Поле creationDate не может быть null")
|
||||
@JsonProperty("creationDate")
|
||||
private ZonedDateTime creationDate; //Поле не может быть null, Значение этого поля должно генерироваться автоматически
|
||||
|
||||
@NotNull(message = "Поле price не может быть null")
|
||||
@Min(value = 1, message = "Поле price не может быть null")
|
||||
@JsonProperty("price")
|
||||
private Long price; //Поле не может быть null, Значение поля должно быть больше 0
|
||||
|
||||
@NotEmpty(message = "Строка partNumber не может быть пустой")
|
||||
@Size(max = 82, message = "Длина строки partNumber не должна быть больше 82")
|
||||
@JsonProperty("partNumber")
|
||||
private String partNumber; //Длина строки не должна быть больше 82, Значение этого поля должно быть уникальным, Строка не может быть пустой, Поле может быть null
|
||||
|
||||
@JsonProperty("manufactureCost")
|
||||
private long manufactureCost;
|
||||
|
||||
@NotNull(message = "Поле unitOfMeasure не может быть null")
|
||||
@JsonProperty("unitOfMeasure")
|
||||
private UnitOfMeasure unitOfMeasure; //Поле не может быть null
|
||||
|
||||
@NotNull(message = "Поле owner не может быть null")
|
||||
@JsonProperty("owner")
|
||||
private Person owner; //Поле не может быть null
|
||||
|
||||
public Product() {}
|
||||
|
||||
public Product (Long id,
|
||||
String name,
|
||||
Coordinates coordinates,
|
||||
Long price,
|
||||
String partNumber,
|
||||
long manufactureCost,
|
||||
UnitOfMeasure unitOfMeasure,
|
||||
Person owner
|
||||
) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.coordinates = coordinates;
|
||||
this.creationDate = ZonedDateTime.now();
|
||||
this.price = price;
|
||||
this.partNumber = partNumber;
|
||||
this.manufactureCost = manufactureCost;
|
||||
this.unitOfMeasure = unitOfMeasure;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Coordinates getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
public ZonedDateTime getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
public Long getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public String getPartNumber() {
|
||||
return partNumber;
|
||||
}
|
||||
|
||||
public long getManufactureCost() {
|
||||
return manufactureCost;
|
||||
}
|
||||
|
||||
public UnitOfMeasure getUnitOfMeasure() {
|
||||
return unitOfMeasure;
|
||||
}
|
||||
|
||||
public Person getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Product{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", coordinates=" + coordinates +
|
||||
", creationDate=" + creationDate +
|
||||
", price=" + price +
|
||||
", partNumber='" + partNumber + '\'' +
|
||||
", manufactureCost=" + manufactureCost +
|
||||
", unitOfMeasure=" + unitOfMeasure +
|
||||
", owner=" + owner +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Product product = (Product) o;
|
||||
return manufactureCost == product.manufactureCost && Objects.equals(id, product.id) && Objects.equals(name, product.name) && Objects.equals(coordinates, product.coordinates) && Objects.equals(creationDate, product.creationDate) && Objects.equals(price, product.price) && Objects.equals(partNumber, product.partNumber) && unitOfMeasure == product.unitOfMeasure && Objects.equals(owner, product.owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name, coordinates, creationDate, price, partNumber, manufactureCost, unitOfMeasure, owner);
|
||||
}
|
||||
}
|
||||
7
src/main/java/me/zinch/models/UnitOfMeasure.java
Normal file
7
src/main/java/me/zinch/models/UnitOfMeasure.java
Normal file
@ -0,0 +1,7 @@
|
||||
package me.zinch.models;
|
||||
|
||||
public enum UnitOfMeasure {
|
||||
KILOGRAMS,
|
||||
CENTIMETERS,
|
||||
GRAMS
|
||||
}
|
||||
18
src/main/java/me/zinch/validator/NotEmpty.java
Normal file
18
src/main/java/me/zinch/validator/NotEmpty.java
Normal file
@ -0,0 +1,18 @@
|
||||
package me.zinch.validator;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = NotEmptyValidator.class)
|
||||
public @interface NotEmpty {
|
||||
String message() default "Value must not be blank";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
11
src/main/java/me/zinch/validator/NotEmptyValidator.java
Normal file
11
src/main/java/me/zinch/validator/NotEmptyValidator.java
Normal file
@ -0,0 +1,11 @@
|
||||
package me.zinch.validator;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
public class NotEmptyValidator implements ConstraintValidator<NotEmpty, String> {
|
||||
@Override
|
||||
public boolean isValid(String value, ConstraintValidatorContext context) {
|
||||
return value == null || !value.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
36
src/main/java/me/zinch/validator/Validators.java
Normal file
36
src/main/java/me/zinch/validator/Validators.java
Normal file
@ -0,0 +1,36 @@
|
||||
package me.zinch.validator;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
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;
|
||||
|
||||
static {
|
||||
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class)
|
||||
.configure()
|
||||
.showValidatedValuesInTraceLogs(false)
|
||||
.buildValidatorFactory();
|
||||
validator = factory.usingContext().getValidator();
|
||||
factory.close();
|
||||
}
|
||||
|
||||
public static boolean validateProduct(Product product) {
|
||||
Set<ConstraintViolation<Product>> violations = validator.validate(product);
|
||||
for (ConstraintViolation<Product> violation : violations) {
|
||||
System.out.println(violation.getMessage());
|
||||
}
|
||||
return violations.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean validateProductList(List<Product> db) {
|
||||
return db.stream().allMatch(Validators::validateProduct);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user