Вынес валидацию из коллекций в команды

This commit is contained in:
Ivan Zinchenko 2024-04-16 21:59:42 +03:00
parent 3578f08f64
commit af50acf548
Signed by: zinch
GPG Key ID: 6D45AA2C8FD6A37E
11 changed files with 102 additions and 50 deletions

2
db.xml
View File

@ -1 +1 @@
<Products><Product><id>341</id><name>Product A</name><coordinates><x>1000</x><y>-500</y></coordinates><creationDate>1711875600.000000000</creationDate><price>1</price><partNumber>part1</partNumber><manufactureCost>1000</manufactureCost><unitOfMeasure>KILOGRAMS</unitOfMeasure><owner><name>John Doe</name><passportID>1234</passportID><hairColor>GREEN</hairColor><location><x>55.5</x><name>Home</name></location></owner></Product></Products>
<Products><Product><id>341</id><name>ewreqr</name><coordinates><x>1432</x><y>132432</y></coordinates><creationDate>1711875600.000000000</creationDate><price>12324</price><partNumber>3214</partNumber><manufactureCost>342</manufactureCost><unitOfMeasure>CENTIMETERS</unitOfMeasure><owner><name>324324</name><passportID>32143214</passportID><hairColor>WHITE</hairColor><location><x>342.0</x><y>423</y><name>214</name></location></owner></Product><Product><id>342</id><name>Hello</name><coordinates><x>13</x><y>4</y></coordinates><creationDate>1713267558.813808800</creationDate><price>12312</price><partNumber>312</partNumber><manufactureCost>321</manufactureCost><unitOfMeasure>CENTIMETERS</unitOfMeasure><owner><name>123</name><passportID>431</passportID><hairColor>BLACK</hairColor><location><x>2321.0</x><y>432</y><name>31</name></location></owner></Product></Products>

View File

@ -2,6 +2,8 @@ package me.zinch.commands;
import me.zinch.console.Console;
import me.zinch.exceptions.CommandActionException;
import me.zinch.exceptions.ValidationException;
import me.zinch.validator.Validators;
import me.zinch.wrapper.ProductCollection;
import java.util.regex.Pattern;
@ -18,7 +20,12 @@ public class Add extends Command {
@Override
public String action(ProductCollection productCollection) throws CommandActionException {
var productDTO = Console.readProductDTO();
var product = productCollection.addProduct(productDTO);
return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId());
try {
Validators.validateObject(productDTO).throwIfNotValid();
var product = productCollection.addProduct(productDTO);
return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId());
} catch (ValidationException e) {
throw new CommandActionException(e.getMessage());
}
}
}

View File

@ -1,6 +1,9 @@
package me.zinch.commands;
import me.zinch.console.Console;
import me.zinch.exceptions.CommandActionException;
import me.zinch.exceptions.ValidationException;
import me.zinch.validator.Validators;
import me.zinch.wrapper.ProductCollection;
import java.util.regex.Pattern;
@ -15,13 +18,17 @@ public class AddIfMax extends Command {
}
@Override
public String action(ProductCollection productCollection) {
public String action(ProductCollection productCollection) throws CommandActionException {
var productDTO = Console.readProductDTO();
var product = productCollection.addIfMaxPrice(productDTO);
if (product.isPresent()) {
return String.format("Продукт %s был добавлен под id %d", product.get().getName(), product.get().getId());
} else {
try {
Validators.validateObject(productDTO).throwIfNotValid();
if (productCollection.getMaxPrice() < productDTO.getPrice()) {
var product = productCollection.addProduct(productDTO);
return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId());
}
return "Продукт не подходит под условие";
} catch (ValidationException e) {
throw new CommandActionException(e.getMessage());
}
}
}

View File

@ -1,6 +1,9 @@
package me.zinch.commands;
import me.zinch.console.Console;
import me.zinch.exceptions.CommandActionException;
import me.zinch.exceptions.ValidationException;
import me.zinch.validator.Validators;
import me.zinch.wrapper.ProductCollection;
import java.util.regex.Pattern;
@ -17,11 +20,15 @@ public class AddIfMin extends Command {
@Override
public String action(ProductCollection productCollection) {
var productDTO = Console.readProductDTO();
var product = productCollection.addIfMinPrice(productDTO);
if (product.isPresent()) {
return String.format("Продукт %s был добавлен под id %d", product.get().getName(), product.get().getId());
} else {
try {
Validators.validateObject(productDTO).throwIfNotValid();
if (productCollection.getMinPrice() > productDTO.getPrice()) {
var product = productCollection.addProduct(productDTO);
return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId());
}
return "Продукт не подходит под условие";
} catch (ValidationException e) {
throw new CommandActionException(e.getMessage());
}
}
}

View File

@ -14,6 +14,6 @@ public class Exit extends Command {
@Override
public String action(ProductCollection productCollection) {
Console.stopApp();
return null;
return "";
}
}

View File

@ -1,6 +1,9 @@
package me.zinch.commands;
import me.zinch.console.Console;
import me.zinch.exceptions.CommandActionException;
import me.zinch.exceptions.ValidationException;
import me.zinch.validator.Validators;
import me.zinch.wrapper.ProductCollection;
import java.util.regex.Pattern;
@ -14,10 +17,18 @@ public class Update extends Command {
}
@Override
public String action(ProductCollection productCollection) {
var productDTO = Console.readProductDTO();
public String action(ProductCollection productCollection) throws CommandActionException {
Long id = Long.parseLong(Console.getLastCommand().split(" ")[1]);
var product = productCollection.updateProduct(id, productDTO);
return String.format("Продукт %s был изменён", product.getName());
if (productCollection.isProductIdExists(id)) {
var productDTO = Console.readProductDTO();
try {
Validators.validateObject(productDTO).throwIfNotValid();
var product = productCollection.updateProduct(id, productDTO);
return String.format("Продукт %s был изменён", product.getName());
} catch (ValidationException e) {
throw new CommandActionException(e.getMessage());
}
}
return "Продукта с таким id не существует";
}
}

View File

@ -5,6 +5,7 @@ import me.zinch.exceptions.ColorFormatException;
import me.zinch.exceptions.CommandActionException;
import me.zinch.exceptions.IllegalProductDtoException;
import me.zinch.exceptions.UnitOfMeasureFormatException;
import me.zinch.exceptions.ValidationException;
import me.zinch.files.DbController;
import me.zinch.models.Color;
import me.zinch.models.Coordinates;
@ -12,6 +13,8 @@ import me.zinch.models.Location;
import me.zinch.models.Person;
import me.zinch.models.ProductDTO;
import me.zinch.models.UnitOfMeasure;
import me.zinch.validator.ValidateResult;
import me.zinch.validator.Validators;
import me.zinch.wrapper.ProductCollection;
import java.io.IOException;
@ -132,8 +135,16 @@ public class Console {
}
}
public static void run() throws IOException {
var productCollection = new ProductCollection(DbController.loadDb());
public static void run() throws IOException, ValidationException {
var productList = DbController.loadDb();
var validationResult = Validators.validateProductList(productList);
if (!validationResult.stream().allMatch(ValidateResult::isValid)) {
throw new ValidationException(String.join("\n", validationResult
.stream()
.map(ValidateResult::getMessage)
.toList()));
}
var productCollection = new ProductCollection(productList);
System.out.println("Добро пожаловать! Для просмотра команд введите help");
while(isRunning) {
System.out.print(":");

View File

@ -15,32 +15,32 @@ import java.time.ZonedDateTime;
* Represents a Data Transfer Object (DTO) for a product with attributes such as name, coordinates, price, part number, manufacture cost, unit of measure, and owner.
*/
public class ProductDTO {
@NotBlank(message = "Строка name не может быть пустой или null")
@NotBlank(message = "ProductDTO: Строка name не может быть пустой или null")
@JsonProperty("name")
private String name; //Поле не может быть null, Строка не может быть пустой
@NotNull(message = "Поле coordinates не может быть null ")
@NotNull(message = "ProductDTO: Поле coordinates не может быть null ")
@JsonProperty("coordinates")
private Coordinates coordinates; //Поле не может быть null
@NotNull(message = "Поле price не может быть null")
@NotNull(message = "ProductDTO: Поле price не может быть null")
@Min(value = 1, message = "Поле price не может быть null")
@JsonProperty("price")
private Long price; //Поле не может быть null, Значение поля должно быть больше 0
@NotEmpty(message = "Строка partNumber не может быть пустой")
@Size(max = 82, message = "Длина строки partNumber не должна быть больше 82")
@NotEmpty(message = "ProductDTO: Строка partNumber не может быть пустой")
@Size(max = 82, message = "ProductDTO: Длина строки partNumber не должна быть больше 82")
@JsonProperty("partNumber")
private String partNumber; //Длина строки не должна быть больше 82, Значение этого поля должно быть уникальным, Строка не может быть пустой, Поле может быть null
@JsonProperty("manufactureCost")
private long manufactureCost;
@NotNull(message = "Поле unitOfMeasure не может быть null")
@NotNull(message = "ProductDTO: Поле unitOfMeasure не может быть null")
@JsonProperty("unitOfMeasure")
private UnitOfMeasure unitOfMeasure; //Поле не может быть null
@NotNull(message = "Поле owner не может быть null")
@NotNull(message = "ProductDTO: Поле owner не может быть null")
@JsonProperty("owner")
private Person owner; //Поле не может быть null

View File

@ -12,13 +12,24 @@ import java.util.Set;
public class ValidateResult<T> {
private final Set<ConstraintViolation<T>> violations;
private final boolean isValid;
private final String message;
public ValidateResult(Set<ConstraintViolation<T>> violations) {
this.violations = violations;
this.isValid = violations.isEmpty();
this.message = null;
}
public ValidateResult(String message) {
this.violations = null;
this.isValid = false;
this.message = message;
}
public String getMessage() {
if (violations == null) {
return message;
}
return String.join("\n", violations.stream().map(ConstraintViolation::getMessage).toList());
}

View File

@ -7,6 +7,7 @@ import me.zinch.models.Product;
import org.hibernate.validator.HibernateValidator;
import java.util.List;
import java.util.Set;
/**
* Utility class for performing validation operations on products.
@ -23,11 +24,20 @@ public class Validators {
factory.close();
}
public static ValidateResult<Product> validateProduct(Product product) {
return new ValidateResult<>(validator.validate(product));
public static <T> ValidateResult<T> validateObject(T t) {
return new ValidateResult<>(validator.validate(t));
}
public static List<ValidateResult<Product>> validateProductList(List<Product> db) {
return db.stream().map(Validators::validateProduct).toList();
var ids = db.stream().map(Product::getId).toList();
var partNumbers = db.stream().map(Product::getPartNumber).toList();
var validations = new java.util.ArrayList<>(db.stream().map(Validators::validateObject).toList());
if (ids.size() != Set.copyOf(ids).size()) {
validations.add(new ValidateResult<>("Поле id должно быть уникальным"));
}
if (partNumbers.size() != Set.copyOf(partNumbers).size()) {
validations.add(new ValidateResult<>("Поле partNumbers должно быть уникальным"));
}
return validations;
}
}

View File

@ -3,8 +3,6 @@ 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;
import java.time.ZoneId;
@ -25,10 +23,6 @@ public class ProductCollection {
public ProductCollection(List<Product> list) throws ValidationException {
productList = new TreeSet<>(Comparator.comparingLong(Product::getId));
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;
}
@ -44,21 +38,18 @@ 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());
}
@ -79,20 +70,17 @@ public class ProductCollection {
productList.clear();
}
public Optional<Product> addIfMaxPrice(ProductDTO productDTO) {
var maxPrice = productList.stream().max(Comparator.comparingLong(Product::getPrice));
if (productList.isEmpty() || productDTO.getPrice() > maxPrice.get().getPrice()) {
return Optional.of(addProduct(productDTO));
}
return Optional.empty();
public Long getMaxPrice() {
return productList.stream().max(Comparator.comparingLong(Product::getPrice)).map(Product::getPrice).orElse(null);
}
public Optional<Product> addIfMinPrice(ProductDTO productDTO) {
var minPrice = productList.stream().min(Comparator.comparingLong(Product::getPrice));
if (productList.isEmpty() || productDTO.getPrice() < minPrice.get().getPrice()) {
return Optional.of(addProduct(productDTO));
}
return Optional.empty();
public Long getMinPrice() {
return productList.stream().min(Comparator.comparingLong(Product::getPrice)).map(Product::getPrice).orElse(null);
}
public boolean isProductIdExists(Long id) {
return getProductById(id) != null;
}
public Integer removeLover(Long id) {