diff --git a/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java index d2323357..31d6b523 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java @@ -12,11 +12,12 @@ import cz.cvut.kbss.analysis.exception.EntityNotFoundException; import cz.cvut.kbss.analysis.exception.ValidationException; import cz.cvut.kbss.analysis.model.util.HasIdentifier; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; +import cz.cvut.kbss.analysis.service.validation.groups.ValidationScopes; import org.springframework.lang.NonNull; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindingResult; import org.springframework.validation.DataBinder; -import org.springframework.validation.Validator; /** @@ -42,9 +43,9 @@ public abstract class BaseRepositoryService { */ protected abstract GenericDao getPrimaryDao(); - private final Validator validator; + private final EntityValidator validator; - protected BaseRepositoryService(Validator validator) { + protected BaseRepositoryService(EntityValidator validator) { this.validator = validator; } @@ -137,7 +138,7 @@ public void persist(@NonNull T instance) { * @param instance The instance to be persisted, not {@code null} */ protected void prePersist(@NonNull T instance) { - validate(instance); + validate(instance, ValidationScopes.Create.class); } protected void postPersist(@NonNull T instance) { @@ -173,7 +174,7 @@ protected void preUpdate(@NonNull T instance) { if (!exists(instance.getUri())) { throw EntityNotFoundException.create(instance.getClass().getSimpleName(), instance.getUri()); } - validate(instance); + validate(instance, ValidationScopes.Update.class); } /** @@ -260,17 +261,25 @@ public boolean existsInPersistenceContext(URI id) { * @param instance The instance to validate * @throws ValidationException In case the instance is not valid */ - protected void validate(T instance) { + public void validate(T instance, Object ... groups) { DataBinder binder = new DataBinder(instance); binder.setValidator(validator); BindingResult bindingResult = binder.getBindingResult(); - validator.validate(instance, bindingResult); + validator.validate(instance, bindingResult, groups); if(bindingResult.hasErrors()) { throw new ValidationException(bindingResult.getAllErrors()); } } + public void validateNew(T instance){ + validate(instance, ValidationScopes.Create.class); + } + + public void validateUpdate(T instance){ + validate(instance, ValidationScopes.Update.class); + } + public URI getToolContext(URI uri){ return getToolContext(uri.toString()); } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java index 4867a5a1..7002e5ab 100644 --- a/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java @@ -6,9 +6,9 @@ import cz.cvut.kbss.analysis.model.ManagedEntity; import cz.cvut.kbss.analysis.model.UserReference; import cz.cvut.kbss.analysis.service.security.SecurityUtils; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import lombok.NonNull; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; import java.util.Arrays; @@ -24,7 +24,7 @@ public abstract class ComplexManagedEntityRepositoryService private final FunctionRepositoryService functionService; @Autowired - public ComponentRepositoryService(@Qualifier("componentValidator") Validator validator, ComponentDao componentDao + public ComponentRepositoryService(@Qualifier("componentValidator") EntityValidator validator, ComponentDao componentDao , FailureModeRepositoryService failureModeRepositoryService, FunctionRepositoryService functionService) { super(validator); this.componentDao = componentDao; @@ -114,6 +114,8 @@ public void deleteFunction(URI componentUri, URI functionUri) { public FailureMode addFailureMode(URI componentUri, FailureMode failureMode) { log.info("> addFailureMode - {}, {}", componentUri, failureMode); + failureModeRepositoryService.validateNew(failureMode); + Component component = findRequired(componentUri); component.addFailureMode(failureMode); update(component); diff --git a/src/main/java/cz/cvut/kbss/analysis/service/FailureModeRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/FailureModeRepositoryService.java index 68ae78fc..c1c7e3b1 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/FailureModeRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/FailureModeRepositoryService.java @@ -3,16 +3,14 @@ import cz.cvut.kbss.analysis.dao.FailureModeDao; import cz.cvut.kbss.analysis.dao.GenericDao; import cz.cvut.kbss.analysis.model.FailureMode; -import cz.cvut.kbss.analysis.model.Function; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; -import java.util.HashSet; import java.util.Set; @Service @@ -23,7 +21,7 @@ public class FailureModeRepositoryService extends BaseRepositoryService getPrimaryDao() { } @Override - protected void validate(FaultEventType instance) { + public void validate(FaultEventType instance, Object ... groups) { } } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java index 89ec2634..c5d5dc8f 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java @@ -4,8 +4,8 @@ import cz.cvut.kbss.analysis.dao.*; import cz.cvut.kbss.analysis.dao.util.FaultTreeFilterParams; import cz.cvut.kbss.analysis.exception.EntityNotFoundException; -import cz.cvut.kbss.analysis.model.*; import cz.cvut.kbss.analysis.model.System; +import cz.cvut.kbss.analysis.model.*; import cz.cvut.kbss.analysis.model.ava.ATASystem; import cz.cvut.kbss.analysis.model.ava.FHAEventType; import cz.cvut.kbss.analysis.model.diagram.Rectangle; @@ -19,6 +19,7 @@ import cz.cvut.kbss.analysis.service.security.SecurityUtils; import cz.cvut.kbss.analysis.service.util.FaultTreeTraversalUtils; import cz.cvut.kbss.analysis.service.util.Pair; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import cz.cvut.kbss.analysis.util.Vocabulary; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; @@ -29,7 +30,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; import java.net.URISyntaxException; @@ -56,7 +56,7 @@ public class FaultTreeRepositoryService extends ComplexManagedEntityRepositorySe private final FailureRateDao failureRateDao; @Autowired - public FaultTreeRepositoryService(@Qualifier("defaultValidator") Validator validator, + public FaultTreeRepositoryService(@Qualifier("defaultEntityValidator") EntityValidator validator, FaultTreeDao faultTreeDao, FaultEventScenarioDao faultEventScenarioDao, FaultEventRepositoryService faultEventRepositoryService, diff --git a/src/main/java/cz/cvut/kbss/analysis/service/FunctionRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/FunctionRepositoryService.java index a4a9f7c7..f716a897 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/FunctionRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/FunctionRepositoryService.java @@ -6,15 +6,18 @@ import cz.cvut.kbss.analysis.model.Behavior; import cz.cvut.kbss.analysis.model.Component; import cz.cvut.kbss.analysis.model.Function; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @Slf4j @Service @@ -24,7 +27,7 @@ public class FunctionRepositoryService extends BaseRepositoryService { private final FailureModeDao failureModeDao; @Autowired - public FunctionRepositoryService(@Qualifier("functionValidator") Validator validator, FunctionDao functionDao, FailureModeDao failureModeDao) { + public FunctionRepositoryService(@Qualifier("functionValidator") EntityValidator validator, FunctionDao functionDao, FailureModeDao failureModeDao) { super(validator); this.functionDao = functionDao; this.failureModeDao = failureModeDao; diff --git a/src/main/java/cz/cvut/kbss/analysis/service/MitigationRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/MitigationRepositoryService.java index 8e203844..02aa46df 100644 --- a/src/main/java/cz/cvut/kbss/analysis/service/MitigationRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/MitigationRepositoryService.java @@ -4,12 +4,12 @@ import cz.cvut.kbss.analysis.dao.MitigationDao; import cz.cvut.kbss.analysis.dto.update.MitigationUpdateDTO; import cz.cvut.kbss.analysis.model.Mitigation; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; @@ -17,10 +17,10 @@ @Service public class MitigationRepositoryService extends BaseRepositoryService { - private MitigationDao mitigationDao; + private final MitigationDao mitigationDao; @Autowired - public MitigationRepositoryService(@Qualifier("defaultValidator") Validator validator, MitigationDao mitigationDao) { + public MitigationRepositoryService(@Qualifier("defaultEntityValidator") EntityValidator validator, MitigationDao mitigationDao) { super(validator); this.mitigationDao = mitigationDao; } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/OperationalDataFilterService.java b/src/main/java/cz/cvut/kbss/analysis/service/OperationalDataFilterService.java index 34377c91..ce1dd810 100644 --- a/src/main/java/cz/cvut/kbss/analysis/service/OperationalDataFilterService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/OperationalDataFilterService.java @@ -114,6 +114,6 @@ protected GenericDao getPrimaryDao() { } @Override - protected void validate(OperationalDataFilter instance) { + public void validate(OperationalDataFilter instance, Object ... groups) { } } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java index b3e7e8f4..3b6ca5d3 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java @@ -11,6 +11,7 @@ import cz.cvut.kbss.analysis.model.System; import cz.cvut.kbss.analysis.model.opdata.OperationalDataFilter; import cz.cvut.kbss.analysis.service.security.SecurityUtils; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import cz.cvut.kbss.analysis.util.Vocabulary; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; @@ -18,7 +19,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; import java.util.HashSet; @@ -37,7 +37,7 @@ public class SystemRepositoryService extends ComplexManagedEntityRepositoryServi private final OperationalDataFilterService operationalDataFilterService; @Autowired - public SystemRepositoryService(@Qualifier("defaultValidator") Validator validator, + public SystemRepositoryService(@Qualifier("systemValidator") EntityValidator validator, SystemDao systemDao, ComponentRepositoryService componentRepositoryService, ComponentDao componentDao, @@ -69,12 +69,6 @@ public System findRequired(URI id) { @Transactional public System create(System system){ - List existingSystems = systemDao.findUriByName(system.getName()); - if(!existingSystems.isEmpty()) - throw new LogicViolationException(( - "Cannot create system with name \"%s\", " + - "the name is already assigned to another system.") - .formatted(system.getName())); this.persist(system); return system; } @@ -96,12 +90,6 @@ public void remove(@NonNull URI instanceUri) { @Transactional public System rename(System systemRename) { log.info("> rename - {}", systemRename); - List existingSystems = systemDao.findUriByName(systemRename.getName()); - if(!existingSystems.isEmpty()) - throw new LogicViolationException(( - "Cannot rename system to \"%s\", " + - "the name is already assigned to another system.") - .formatted(systemRename.getName())); System system = findRequired(systemRename.getUri()); system.setName(systemRename.getName()); diff --git a/src/main/java/cz/cvut/kbss/analysis/service/UserRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/UserRepositoryService.java index 269d2746..9d80c8db 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/UserRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/UserRepositoryService.java @@ -7,13 +7,13 @@ import cz.cvut.kbss.analysis.exception.UsernameNotAvailableException; import cz.cvut.kbss.analysis.model.User; import cz.cvut.kbss.analysis.service.security.SecurityUtils; +import cz.cvut.kbss.analysis.service.validation.EntityValidator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.Validator; import java.net.URI; import java.util.Optional; @@ -27,7 +27,7 @@ public class UserRepositoryService extends BaseRepositoryService { private final SecurityUtils securityUtils; @Autowired - public UserRepositoryService(@Qualifier("defaultValidator") Validator validator, UserDao userDao, PasswordEncoder passwordEncoder, SecurityUtils securityUtils) { + public UserRepositoryService(@Qualifier("defaultEntityValidator") EntityValidator validator, UserDao userDao, PasswordEncoder passwordEncoder, SecurityUtils securityUtils) { super(validator); this.userDao = userDao; this.passwordEncoder = passwordEncoder; diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/ComponentValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/ComponentValidator.java index ff3ae24e..b463a6b2 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/validation/ComponentValidator.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/ComponentValidator.java @@ -1,40 +1,26 @@ package cz.cvut.kbss.analysis.service.validation; +import cz.cvut.kbss.analysis.dao.BaseDao; import cz.cvut.kbss.analysis.dao.ComponentDao; import cz.cvut.kbss.analysis.model.Component; -import cz.cvut.kbss.analysis.util.Vocabulary; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; @Qualifier("componentValidator") @Slf4j @org.springframework.stereotype.Component -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -public class ComponentValidator implements Validator { +public class ComponentValidator extends NamedEntityValidator { private final ComponentDao componentDao; - private final SpringValidatorAdapter validatorAdapter; - @Override - public boolean supports(Class clazz) { - return Component.class.isAssignableFrom(clazz); + public ComponentValidator(SpringValidatorAdapter validatorAdapter, ComponentDao componentDao) { + super(Component.class, validatorAdapter); + this.componentDao = componentDao; } @Override - public void validate(Object target, Errors errors) { - validatorAdapter.validate(target, errors); - - Component instance = (Component) target; - - boolean duplicate = componentDao.existsWithPredicate(Vocabulary.s_p_name, instance.getName()); - if(instance.getUri() == null && duplicate) { - errors.rejectValue("name", "name.duplicate", "Duplicate component name"); - } + protected BaseDao getPrimaryDao() { + return componentDao; } - } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/DefaultEntityValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/DefaultEntityValidator.java new file mode 100644 index 00000000..e5e800c5 --- /dev/null +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/DefaultEntityValidator.java @@ -0,0 +1,28 @@ +package cz.cvut.kbss.analysis.service.validation; + +import cz.cvut.kbss.analysis.dao.BaseDao; +import cz.cvut.kbss.analysis.model.NamedEntity; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.validation.Errors; +import org.springframework.validation.beanvalidation.SpringValidatorAdapter; + +@Qualifier("defaultEntityValidator") +@Slf4j +@org.springframework.stereotype.Component +public class DefaultEntityValidator extends NamedEntityValidator{ + + public DefaultEntityValidator(SpringValidatorAdapter validatorAdapter) { + super(NamedEntity.class, validatorAdapter); + } + + @Override + protected BaseDao getPrimaryDao() { + return null; + } + + @Override + protected void customValidation(Object target, Errors errors, Object... validationHints) { + // No custom validation + } +} diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/EntityValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/EntityValidator.java new file mode 100644 index 00000000..b69e8696 --- /dev/null +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/EntityValidator.java @@ -0,0 +1,9 @@ +package cz.cvut.kbss.analysis.service.validation; + +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +public interface EntityValidator extends Validator { + + void validate(Object target, Errors errors, Object... validationHints); +} diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultEventValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultEventValidator.java index 170cfe88..7b7e0d8d 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultEventValidator.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultEventValidator.java @@ -1,44 +1,37 @@ package cz.cvut.kbss.analysis.service.validation; +import cz.cvut.kbss.analysis.dao.BaseDao; import cz.cvut.kbss.analysis.dao.FaultEventDao; import cz.cvut.kbss.analysis.model.FaultEvent; import cz.cvut.kbss.analysis.model.fta.FtaEventType; import cz.cvut.kbss.analysis.model.fta.GateType; -import cz.cvut.kbss.analysis.util.Vocabulary; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; -import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; @Qualifier("faultEventValidator") @Slf4j @Component -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -public class FaultEventValidator implements Validator { +public class FaultEventValidator extends NamedEntityValidator { private final FaultEventDao faultEventDao; - private final SpringValidatorAdapter validatorAdapter; - @Override - public boolean supports(Class clazz) { - return FaultEvent.class.isAssignableFrom(clazz); + public FaultEventValidator(SpringValidatorAdapter validatorAdapter, FaultEventDao faultEventDao) { + super(FaultEvent.class, validatorAdapter); + this.faultEventDao = faultEventDao; } @Override - public void validate(Object target, Errors errors) { - validatorAdapter.validate(target, errors); + protected BaseDao getPrimaryDao() { + return faultEventDao; + } + protected void customValidation(Object target, Errors errors, Object... validationHints ){ + super.customValidation(target, errors, validationHints); FaultEvent instance = (FaultEvent) target; - boolean duplicate = faultEventDao.existsWithPredicate(Vocabulary.s_p_name, instance.getName()); - if(instance.getUri() == null && duplicate) { - errors.rejectValue("name", "name.duplicate"); - } - if (instance.getEventType() == FtaEventType.INTERMEDIATE && (instance.getGateType() == null || instance.getGateType() == GateType.UNUSED)) { errors.rejectValue("gateType", "gateType.invalid"); } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultTreeValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultTreeValidator.java index cb84b51d..e0e0c4c4 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultTreeValidator.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/FaultTreeValidator.java @@ -1,50 +1,27 @@ package cz.cvut.kbss.analysis.service.validation; -import cz.cvut.kbss.analysis.dao.FaultEventDao; -import cz.cvut.kbss.analysis.model.FaultEvent; -import cz.cvut.kbss.analysis.model.fta.FtaEventType; -import cz.cvut.kbss.analysis.model.fta.GateType; -import cz.cvut.kbss.analysis.util.Vocabulary; -import lombok.RequiredArgsConstructor; +import cz.cvut.kbss.analysis.dao.BaseDao; +import cz.cvut.kbss.analysis.dao.FaultTreeDao; +import cz.cvut.kbss.analysis.model.FaultTree; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; @Qualifier("faultTreeValidator") @Slf4j @Component -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -public class FaultTreeValidator implements Validator { +public class FaultTreeValidator extends NamedEntityValidator { - private final FaultEventDao faultEventDao; - private final SpringValidatorAdapter validatorAdapter; + private final FaultTreeDao faultTreeDao; - @Override - public boolean supports(Class clazz) { - return FaultEvent.class.isAssignableFrom(clazz); + public FaultTreeValidator(SpringValidatorAdapter validatorAdapter, FaultTreeDao faultTreeDao) { + super(FaultTree.class, validatorAdapter); + this.faultTreeDao = faultTreeDao; } @Override - public void validate(Object target, Errors errors) { - validatorAdapter.validate(target, errors); - - FaultEvent instance = (FaultEvent) target; - - boolean duplicate = faultEventDao.existsWithPredicate(Vocabulary.s_p_name, instance.getName()); - if(instance.getUri() == null && duplicate) { - errors.rejectValue("name", "name.duplicate"); - } - - if (instance.getEventType() == FtaEventType.INTERMEDIATE && (instance.getGateType() == null || instance.getGateType() == GateType.UNUSED)) { - errors.rejectValue("gateType", "gateType.invalid"); - } - - if (instance.getEventType() != FtaEventType.INTERMEDIATE && (instance.getGateType() != null || instance.getGateType() != GateType.UNUSED)) { - errors.rejectValue("gateType", "gateType.invalid"); - } + protected BaseDao getPrimaryDao() { + return faultTreeDao; } } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/FunctionValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/FunctionValidator.java index 6614c0bf..620c9a9b 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/validation/FunctionValidator.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/FunctionValidator.java @@ -1,40 +1,28 @@ package cz.cvut.kbss.analysis.service.validation; +import cz.cvut.kbss.analysis.dao.BaseDao; import cz.cvut.kbss.analysis.dao.FunctionDao; import cz.cvut.kbss.analysis.model.Function; -import cz.cvut.kbss.analysis.util.Vocabulary; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; +import org.springframework.stereotype.Component; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; @Qualifier("functionValidator") @Slf4j -@org.springframework.stereotype.Component -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -public class FunctionValidator implements Validator { +@Component +public class FunctionValidator extends NamedEntityValidator { private final FunctionDao functionDao; - private final SpringValidatorAdapter validatorAdapter; - @Override - public boolean supports(Class clazz) { - return Function.class.isAssignableFrom(clazz); + public FunctionValidator(SpringValidatorAdapter validatorAdapter, FunctionDao functionDao) { + super(Function.class, validatorAdapter); + this.functionDao = functionDao; } @Override - public void validate(Object target, Errors errors) { - validatorAdapter.validate(target, errors); - - Function instance = (Function) target; - - boolean duplicate = functionDao.existsWithPredicate(Vocabulary.s_p_name, instance.getName()); - if(instance.getUri() == null && duplicate) { - errors.rejectValue("name", "name.duplicate", "Duplicate component name"); - } + protected BaseDao getPrimaryDao() { + return functionDao; } } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/NamedEntityValidator.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/NamedEntityValidator.java new file mode 100644 index 00000000..763dd82b --- /dev/null +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/NamedEntityValidator.java @@ -0,0 +1,101 @@ +package cz.cvut.kbss.analysis.service.validation; + +import cz.cvut.kbss.analysis.dao.BaseDao; +import cz.cvut.kbss.analysis.model.NamedEntity; +import cz.cvut.kbss.analysis.service.validation.groups.ValidationScopes; +import cz.cvut.kbss.analysis.util.Vocabulary; +import jakarta.validation.Validator; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.Errors; +import org.springframework.validation.beanvalidation.SpringValidatorAdapter; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Slf4j +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public abstract class NamedEntityValidator implements EntityValidator { + + protected final Class supporetedClass; + protected final SpringValidatorAdapter validatorAdapter; + + @Override + public boolean supports(Class clazz) { + Validator v; + + return supporetedClass.isAssignableFrom(clazz); + } + + @Override + public void validate(Object target, Errors errors, Object... validationHints) { + validatorAdapter.validate(target, errors, validationHints); + customValidation(target, errors, validationHints); + } + + @Override + public void validate(Object target, Errors errors) { + validatorAdapter.validate(target, errors); + customValidation(target, errors); + } + + protected abstract BaseDao getPrimaryDao(); + + protected void customValidation(Object target, Errors errors, Object... validationHints ){ + ConstraintGroupsAdapter groups = new ConstraintGroupsAdapter(validationHints); + NamedEntity entity = (NamedEntity) target; + + if(existsWithName(entity)) + errors.rejectValue("name", "name.duplicate", "Duplicate entity name"); + + if(groups.isCreateGroup() && exists(entity)){ + errors.rejectValue("uri", "uri.exists", "The uri should be null or unique"); + } + if(groups.isUpdateGroup() && !exists(entity)){ + errors.rejectValue("uri", "uri.not-exists", "Uri does not refer to an existing entity"); + } + } + + protected boolean exists(NamedEntity entity){ + return entity.getUri() != null && getPrimaryDao().exists(entity.getUri()); + } + + protected boolean existsWithName(NamedEntity entity){ + return existsWithName(entity.getName()); + } + + protected boolean existsWithName(String name){ + return name != null && !name.isBlank() && + getPrimaryDao().existsWithPredicate(Vocabulary.s_p_name, name); + } + + static class ConstraintGroupsAdapter{ + Set groups; + + public ConstraintGroupsAdapter(Object... groups) { + this.groups = classSet(groups); + } + + public Set classSet(Object... groups){ + return Stream.of(groups) + .filter(o -> o != null) + .filter(o -> o instanceof Class) + .map(o -> (Class)o) + .collect(Collectors.toSet()); + } + + public boolean matchesAll(Object ... groups) { + if(groups.length == 0) return true; + return classSet(groups).stream().allMatch(t -> this.groups.stream().anyMatch(g -> g.isAssignableFrom(t))); + } + + public boolean isCreateGroup() { + return matchesAll(ValidationScopes.Create.class); + } + public boolean isUpdateGroup() { + return matchesAll(ValidationScopes.Update.class); + } + } +} diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/ValidatorsConfiguration.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/ValidatorsConfiguration.java new file mode 100644 index 00000000..5fa4c603 --- /dev/null +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/ValidatorsConfiguration.java @@ -0,0 +1,37 @@ +package cz.cvut.kbss.analysis.service.validation; + +import cz.cvut.kbss.analysis.dao.*; +import cz.cvut.kbss.analysis.model.System; +import cz.cvut.kbss.analysis.model.*; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.beanvalidation.SpringValidatorAdapter; + +@Configuration +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ValidatorsConfiguration { + + private final SpringValidatorAdapter validatorAdapter; + + @Bean("systemValidator") + public NamedEntityValidator systemValidator(SystemDao dao){ + return createCommonValidator(System.class, dao); + } + + @Bean(name ="failureModeValidator") + public NamedEntityValidator failureModeValidator(FailureModeDao dao){ + return createCommonValidator(FailureMode.class, dao); + } + + protected NamedEntityValidator createCommonValidator(Class cls, BaseDao dao){ + return new NamedEntityValidator(cls, validatorAdapter) { + private final BaseDao baseDao = dao; + @Override + protected BaseDao getPrimaryDao() { + return baseDao; + } + }; + } +} diff --git a/src/main/java/cz/cvut/kbss/analysis/service/validation/groups/ValidationScopes.java b/src/main/java/cz/cvut/kbss/analysis/service/validation/groups/ValidationScopes.java new file mode 100644 index 00000000..ab6524a7 --- /dev/null +++ b/src/main/java/cz/cvut/kbss/analysis/service/validation/groups/ValidationScopes.java @@ -0,0 +1,6 @@ +package cz.cvut.kbss.analysis.service.validation.groups; + +public interface ValidationScopes { + interface Create {} + interface Update {} +}