From 5b82cf4d22ec95acb672671d378b443ebbeda37b Mon Sep 17 00:00:00 2001 From: akulikov Date: Fri, 13 Jan 2023 14:08:21 +0300 Subject: [PATCH] validators --- .../clearing/scheduler/IRequestValidator.java | 179 ++++++++++++++++++ .../service/ClearingCalendarService.java | 22 +++ .../scheduler/service/PlannerService.java | 11 ++ .../service/PlannerTemplateService.java | 11 ++ 4 files changed, 223 insertions(+) create mode 100644 clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/IRequestValidator.java diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/IRequestValidator.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/IRequestValidator.java new file mode 100644 index 000000000..47e0e83db --- /dev/null +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/IRequestValidator.java @@ -0,0 +1,179 @@ +package ru.spcex.clearing.scheduler; + +import org.slf4j.Logger; +import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.schedule.*; +import ru.spcex.platform.enumeration.DayStatus; +import ru.spcex.platform.enumeration.Market; +import ru.spcex.platform.enumeration.Status; +import ru.spcex.platform.enumeration.Task; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +public interface IRequestValidator { + List validate(T req); + + /** + * Общий запрос на удаление + */ + IRequestValidator COMMON_DELETE_REQUEST = req -> { + var errors = new LinkedList(); + validateLong(req.id, "id", true, errors); + return errors; + }; + + /** + * Запрос на добавление ClearingCalendar + */ + IRequestValidator CLEARING_CALENDAR_NEW_REQUEST = req -> { + var errors = new LinkedList(); + validateDate(req.clearingDate, "clearingDate", true, true, errors); + validateLong(req.companyId, "companyId", false, errors); + validateEnum(req.dayStatus, "dayStatus", true, errors, DayStatus.values()); + return errors; + }; + + /** + * Запрос на обновление ClearingCalendar + */ + IRequestValidator CLEARING_CALENDAR_UPDATE_REQUEST = req -> { + var errors = new LinkedList(); + validateLong(req.id, "id", true, errors); + validateLong(req.companyId, "companyId", false, errors); + validateDate(req.clearingDate, "clearingDate", false, true, errors); + validateEnum(req.dayStatus, "dayStatus", false, errors, DayStatus.values()); + return errors; + }; + + /** + * Запрос на добавление Planner + */ + IRequestValidator PLANNER_NEW_REQUEST = req -> { + var errors = new LinkedList(); + validateEnum(req.task, "task", true, errors, Task.values()); + validateDate(req.clearingDate, "clearingDate", true, true, errors); + validateTime(req.taskTime, "taskTime", true, true, errors); + validateEnum(req.market, "market", false, errors, Market.values()); + validateEnum(req.taskStatus, "taskStatus", true, errors, Status.values()); + validateLong(req.companyId, "companyId", false, errors); + validateLong(req.securityId, "securityId", false, errors); + return errors; + }; + + /** + * Запрос на обновление Planner + */ + IRequestValidator PLANNER_UPDATE_REQUEST = req -> { + var errors = new LinkedList(); + validateLong(req.id, "id", true, errors); + validateEnum(req.task, "task", false, errors, Task.values()); + validateDate(req.clearingDate, "clearingDate", false, true, errors); + validateTime(req.taskTime, "taskTime", false, true, errors); + validateEnum(req.market, "market", false, errors, Market.values()); + validateEnum(req.taskStatus, "taskStatus", false, errors, Status.values()); + validateLong(req.companyId, "companyId", false, errors); + validateLong(req.securityId, "securityId", false, errors); + return errors; + }; + + /** + * Запрос на добавление PlannerTemplate + */ + IRequestValidator PLANNER_TEMPLATE_NEW_REQUEST = req -> { + var errors = new LinkedList(); + validateEnum(req.task, "task", true, errors, Task.values()); + validateTime(req.taskTime, "taskTime", true, true, errors); + validateEnum(req.taskStatus, "taskStatus", true, errors, Status.values()); + validateLong(req.companyId, "companyId", false, errors); + validateLong(req.securityId, "securityId", false, errors); + return errors; + }; + + /** + * Запрос на обновление PlannerTemplate + */ + IRequestValidator PLANNER_TEMPLATE_UPDATE_REQUEST = req -> { + var errors = new LinkedList(); + validateLong(req.id, "id", true, errors); + validateEnum(req.task, "task", false, errors, Task.values()); + validateTime(req.taskTime, "taskTime", false, true, errors); + validateEnum(req.taskStatus, "taskStatus", false, errors, Status.values()); + validateLong(req.companyId, "companyId", false, errors); + validateLong(req.securityId, "securityId", false, errors); + return errors; + }; + + + + + static & IEnumKey> void validateEnum(String enumStr, + String fieldName, + boolean required, + List errors, + T... enumSet) { + if (enumStr != null) { + boolean correctTask = IEnumKey.contains(enumStr, enumSet); + if (!correctTask) + errors.add(new ValidationError(fieldName, ErrorType.UNKNOWN_VALUE)); + } else if (required) errors.add(new ValidationError(fieldName, ErrorType.MISSING_REQUIRED)); + } + + static void validateLong(Long value, String fieldName, boolean required, List errors) { + if (value != null) { + if (value < 0 || value == Long.MAX_VALUE) + errors.add(new ValidationError(fieldName, ErrorType.INVALID_VALUE)); + } else if (required) errors.add(new ValidationError(fieldName, ErrorType.MISSING_REQUIRED)); + } + + static void validateDate(LocalDate value, + String fieldName, + boolean required, + boolean checkDate, + List errors) { + if (value != null) { + if (checkDate && (value.isBefore(LocalDate.now()))) + errors.add(new ValidationError(fieldName, ErrorType.INVALID_VALUE)); + } else if (required) errors.add(new ValidationError(fieldName, ErrorType.MISSING_REQUIRED)); + } + + static void validateTime(LocalTime value, + String fieldName, + boolean required, + boolean checkDate, + List errors) { + if (value != null) { + if (checkDate && (value.isBefore(LocalTime.now()))) + errors.add(new ValidationError(fieldName, ErrorType.INVALID_VALUE)); + } else if (required) errors.add(new ValidationError(fieldName, ErrorType.MISSING_REQUIRED)); + } + + /** + * Временный метод + */ + static boolean checkErrorList(List errors, Logger log) { + if (!errors.isEmpty()) { + log.error("Validation error: [{}]", + errors.stream().map(IRequestValidator.ValidationError::toString).collect(Collectors.joining(", ")) + ); + return true; + } + return false; + } + + enum ErrorType { + MISSING_REQUIRED, UNKNOWN_VALUE, INVALID_VALUE + } + + record ValidationError(String fieldName, ErrorType errorType) { + @Override + public String toString() { + return "%s: %s".formatted(fieldName, errorType); + } + } + +} diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java index 3a86684b7..0c347b70c 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java @@ -15,15 +15,21 @@ import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteReques import ru.spcex.clearing.platform.messaging.domain.cud.schedule.ClearingCalendarNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.ClearingCalendarUpdateRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.scheduler.IRequestValidator; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import java.time.Instant; +import java.util.List; +import java.util.stream.Collectors; @Service public class ClearingCalendarService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg clearingCalendarMap; + private final IRequestValidator newRequestValidator = IRequestValidator.CLEARING_CALENDAR_NEW_REQUEST; + private final IRequestValidator updateRequestValidator = IRequestValidator.CLEARING_CALENDAR_UPDATE_REQUEST; + private final IRequestValidator deleteRequestValidator = IRequestValidator.COMMON_DELETE_REQUEST; @Autowired public ClearingCalendarService(Consumer kafkaQueue, Producer kafkaProducer, @@ -49,6 +55,8 @@ public class ClearingCalendarService extends QueueConsumer implements Initializi private void newClearingCalendar(BaseRequest userRequest) { ClearingCalendarNewRequest req = userRequest.getRequestPayload(); log.debug("ClearingCalendarNewRequest received"); + List errors = newRequestValidator.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; ClearingCalendar clearingCalendar = new ClearingCalendar(); Instant created = Instant.now(); clearingCalendar.setCreated(created); @@ -62,6 +70,8 @@ public class ClearingCalendarService extends QueueConsumer implements Initializi private void updateClearingCalendar(BaseRequest userRequest) { ClearingCalendarUpdateRequest req = userRequest.getRequestPayload(); log.debug("ClearingCalendarUpdateRequest received"); + List errors = updateRequestValidator.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; Instant updated = Instant.now(); ClearingCalendar clearingCalendar = clearingCalendarMap.getSingleObjectByID(req.getId()); clearingCalendar.setClearingDate(req.getClearingDate()); @@ -74,8 +84,20 @@ public class ClearingCalendarService extends QueueConsumer implements Initializi private void deleteClearingCalendar(BaseRequest userRequest) { CommonDeleteRequest req = userRequest.getRequestPayload(); + List errors = deleteRequestValidator.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; log.debug("CommonDeleteRequest received id = {}", req.getId()); ClearingCalendar clearingCalendar = clearingCalendarMap.getSingleObjectByID(req.getId()); clearingCalendarMap.delete(clearingCalendar); } + + static boolean checkErrors(List errors, Logger log) { + if (!errors.isEmpty()) { + log.error("Validation error: [{}]", + errors.stream().map(IRequestValidator.ValidationError::toString).collect(Collectors.joining(", ")) + ); + return true; + } + return false; + } } diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerService.java index 199c12ab4..53dc8a791 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerService.java @@ -15,15 +15,20 @@ import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteReques import ru.spcex.clearing.platform.messaging.domain.cud.schedule.PlannerNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.PlannerUpdateRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.scheduler.IRequestValidator; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import java.time.Instant; +import java.util.List; @Service public class PlannerService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg plannerMap; + private final IRequestValidator plannerNewRequest = IRequestValidator.PLANNER_NEW_REQUEST; + private final IRequestValidator plannerUpdateRequest = IRequestValidator.PLANNER_UPDATE_REQUEST; + private final IRequestValidator deleteRequestValidator = IRequestValidator.COMMON_DELETE_REQUEST; @Autowired public PlannerService(Consumer kafkaQueue, Producer kafkaProducer, @@ -49,6 +54,8 @@ public class PlannerService extends QueueConsumer implements InitializingBean { private void newScheduler(BaseRequest userRequest) { PlannerNewRequest req = userRequest.getRequestPayload(); log.debug("PlannerNewRequest received"); + List errors = plannerNewRequest.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; Planner planner = new Planner(); planner.setCreated(Instant.now()); planner.setTask(req.getTask()); @@ -65,6 +72,8 @@ public class PlannerService extends QueueConsumer implements InitializingBean { private void updateScheduler(BaseRequest userRequest) { PlannerUpdateRequest req = userRequest.getRequestPayload(); log.debug("PlannerUpdateRequest received id = {}", req.getId()); + List errors = plannerUpdateRequest.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; Planner planner = plannerMap.getSingleObjectByID(req.getId()); planner.setUpdated(Instant.now()); planner.setTask(req.getTask()); @@ -80,6 +89,8 @@ public class PlannerService extends QueueConsumer implements InitializingBean { private void deleteScheduler(BaseRequest userRequest) { CommonDeleteRequest req = userRequest.getRequestPayload(); log.debug("CommonDeleteRequest received id = {}", req.getId()); + List errors = deleteRequestValidator.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; Planner planner = plannerMap.getSingleObjectByID(req.getId()); plannerMap.delete(planner); } diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java index 77a1466a0..0d9d12b33 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java @@ -15,15 +15,20 @@ import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteReques import ru.spcex.clearing.platform.messaging.domain.cud.schedule.PlannerTemplateNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.PlannerTemplateUpdateRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.scheduler.IRequestValidator; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import java.time.Instant; +import java.util.List; @Service public class PlannerTemplateService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg plannerTemplateMap; + private final IRequestValidator plannerTemplateNewRequest = IRequestValidator.PLANNER_TEMPLATE_NEW_REQUEST; + private final IRequestValidator plannerTemplateUpdateRequest = IRequestValidator.PLANNER_TEMPLATE_UPDATE_REQUEST; + private final IRequestValidator deleteRequestValidator = IRequestValidator.COMMON_DELETE_REQUEST; @Autowired public PlannerTemplateService(Consumer kafkaQueue, Producer kafkaProducer, @@ -49,6 +54,8 @@ public class PlannerTemplateService extends QueueConsumer implements Initializin private void newTimetable(BaseRequest userRequest) { PlannerTemplateNewRequest req = userRequest.getRequestPayload(); log.debug("PlannerTemplateNewRequest received"); + List errors = plannerTemplateNewRequest.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; PlannerTemplate plannerTemplate = new PlannerTemplate(); Instant created = Instant.now(); plannerTemplate.setCreated(created); @@ -65,6 +72,8 @@ public class PlannerTemplateService extends QueueConsumer implements Initializin PlannerTemplateUpdateRequest req = userRequest.getRequestPayload(); log.debug("PlannerTemplateUpdateRequest received"); PlannerTemplate plannerTemplate = plannerTemplateMap.getSingleObjectByID(req.getId()); + List errors = plannerTemplateUpdateRequest.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; Instant updated = Instant.now(); plannerTemplate.setUpdated(updated); plannerTemplate.setTask(req.getTask()); @@ -79,6 +88,8 @@ public class PlannerTemplateService extends QueueConsumer implements Initializin private void deleteTimetable(BaseRequest userRequest) { CommonDeleteRequest req = userRequest.getRequestPayload(); log.debug("CommonDeleteRequest received id = {}", req.getId()); + List errors = deleteRequestValidator.validate(req); + if (IRequestValidator.checkErrorList(errors, log)) return; PlannerTemplate plannerTemplate = plannerTemplateMap.getSingleObjectByID(req.getId()); plannerTemplateMap.delete(plannerTemplate); }