add multiplicity validation to description persist

This commit is contained in:
amentis 2024-04-02 15:46:17 +03:00
parent bc16f8a2c4
commit 27e6677a21
7 changed files with 58 additions and 19 deletions

View File

@ -1,15 +1,19 @@
package eu.eudat.model.persist; package eu.eudat.model.persist;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.XmlHandlingService;
import eu.eudat.commons.enums.DescriptionStatus; import eu.eudat.commons.enums.DescriptionStatus;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity;
import eu.eudat.commons.types.dmpblueprint.SectionEntity;
import eu.eudat.commons.validation.BaseValidator; import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.convention.ConventionService; import eu.eudat.convention.ConventionService;
import eu.eudat.data.DescriptionEntity; import eu.eudat.data.*;
import eu.eudat.data.DescriptionTemplateEntity;
import eu.eudat.data.TenantEntityManager;
import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.model.persist.descriptionproperties.PropertyDefinitionPersist; import eu.eudat.model.persist.descriptionproperties.PropertyDefinitionPersist;
import eu.eudat.query.DescriptionQuery;
import eu.eudat.query.DmpDescriptionTemplateQuery;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.validation.specification.Specification; import gr.cite.tools.validation.specification.Specification;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
@ -21,6 +25,7 @@ import javax.management.InvalidApplicationException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
public class DescriptionPersist { public class DescriptionPersist {
@ -151,12 +156,14 @@ public class DescriptionPersist {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
private final XmlHandlingService xmlHandlingService; private final XmlHandlingService xmlHandlingService;
private final QueryFactory queryFactory;
protected DescriptionPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, TenantEntityManager entityManager, XmlHandlingService xmlHandlingService) { protected DescriptionPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, TenantEntityManager entityManager, XmlHandlingService xmlHandlingService, QueryFactory queryFactory) {
super(conventionService, errors); super(conventionService, errors);
this.messageSource = messageSource; this.messageSource = messageSource;
this.entityManager = entityManager; this.entityManager = entityManager;
this.xmlHandlingService = xmlHandlingService; this.xmlHandlingService = xmlHandlingService;
this.queryFactory = queryFactory;
} }
@Override @Override
@ -167,12 +174,18 @@ public class DescriptionPersist {
@Override @Override
protected List<Specification> specifications(DescriptionPersist item) { protected List<Specification> specifications(DescriptionPersist item) {
DescriptionTemplateEntity descriptionTemplate = null; DescriptionTemplateEntity descriptionTemplate = null;
DmpEntity dmpEntity = null;
DmpBlueprintEntity dmpBlueprintEntity = null;
try { try {
descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId()) : null; descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId()) : null;
dmpEntity = this.isValidGuid(item.getDmpId()) ? this.entityManager.find(DmpEntity.class, item.getDmpId()) : null;
dmpBlueprintEntity = this.entityManager.find(DmpBlueprintEntity.class, dmpEntity.getBlueprintId());
} catch (InvalidApplicationException e) { } catch (InvalidApplicationException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition()); DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition());
DmpBlueprintEntity finalDmpBlueprintEntity = dmpBlueprintEntity;
return Arrays.asList( return Arrays.asList(
this.spec() this.spec()
.iff(() -> this.isValidGuid(item.getId())) .iff(() -> this.isValidGuid(item.getId()))
@ -204,7 +217,11 @@ public class DescriptionPersist {
this.spec() this.spec()
.iff(() -> item.getStatus() == DescriptionStatus.Finalized) .iff(() -> item.getStatus() == DescriptionStatus.Finalized)
.must(() -> !this.isNull(item.getProperties())) .must(() -> !this.isNull(item.getProperties()))
.failOn(DescriptionPersist._properties).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())) .failOn(DescriptionPersist._properties).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
.must(() -> this.isDescriptionTemplateMultiplicityValid(finalDmpBlueprintEntity, item.getDmpId(), item.getDescriptionTemplateId()))
.failOn(DescriptionPersist._descriptionTemplateId).failWith(messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicity", new Object[]{DescriptionPersist._descriptionTemplateId}, LocaleContextHolder.getLocale()))
// this.refSpec() // this.refSpec()
// .iff(() -> !this.isNull(item.getProperties())) // .iff(() -> !this.isNull(item.getProperties()))
// .on(DescriptionPersist._properties) // .on(DescriptionPersist._properties)
@ -217,6 +234,35 @@ public class DescriptionPersist {
// .using((itm) -> this.validatorFactory.validator(TagPersist.TagPersistValidator.class)) // .using((itm) -> this.validatorFactory.validator(TagPersist.TagPersistValidator.class))
); );
} }
private boolean isDescriptionTemplateMultiplicityValid(DmpBlueprintEntity dmpBlueprintEntity, UUID dmpId, UUID descriptionTemplateId){
eu.eudat.commons.types.dmpblueprint.DefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(eu.eudat.commons.types.dmpblueprint.DefinitionEntity.class, dmpBlueprintEntity.getDefinition());
if (definition == null || this.isListNullOrEmpty(definition.getSections())) return true;
for (SectionEntity section: definition.getSections()) {
if (section.getHasTemplates() && !this.isListNullOrEmpty(section.getDescriptionTemplates())){
int descriptionsCount = 0;
for (eu.eudat.commons.types.dmpblueprint.DescriptionTemplateEntity sectionDescriptionTemplate: section.getDescriptionTemplates()) {
if (sectionDescriptionTemplate.getMaxMultiplicity() == null && sectionDescriptionTemplate.getMinMultiplicity() == null ) continue;
DmpDescriptionTemplateQuery dmpDescriptionTemplateQuery = this.queryFactory.query(DmpDescriptionTemplateQuery.class).isActive(IsActive.Active).dmpIds(dmpId).sectionIds(section.getId());
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).dmpIds(dmpId).dmpDescriptionTemplateSubQuery(dmpDescriptionTemplateQuery).isActive(IsActive.Active).collect();
if (this.isListNullOrEmpty(descriptionEntities)) continue;
for (DescriptionEntity description: descriptionEntities){
if (description.getDescriptionTemplateId().equals(descriptionTemplateId)) descriptionsCount++;
}
if (sectionDescriptionTemplate.getMinMultiplicity() != null && sectionDescriptionTemplate.getMinMultiplicity() >= descriptionsCount) return false;
if (sectionDescriptionTemplate.getMaxMultiplicity() != null && sectionDescriptionTemplate.getMaxMultiplicity() <= descriptionsCount) return false;
}
}
}
return true;
}
} }
} }

View File

@ -95,11 +95,7 @@ public class DescriptionTemplatePersist {
this.spec() this.spec()
.iff(() -> !this.isNull(item.getMaxMultiplicity())) .iff(() -> !this.isNull(item.getMaxMultiplicity()))
.must(() -> item.getMaxMultiplicity() > 0) .must(() -> item.getMaxMultiplicity() > 0)
.failOn(DescriptionTemplatePersist._maxMultiplicity).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{DescriptionTemplatePersist._maxMultiplicity}, LocaleContextHolder.getLocale())), .failOn(DescriptionTemplatePersist._maxMultiplicity).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{DescriptionTemplatePersist._maxMultiplicity}, LocaleContextHolder.getLocale()))
this.spec()
.iff(() -> !this.isNull(item.getMaxMultiplicity()))
.must(() -> !this.isNull(item.getMinMultiplicity()) && (item.getMaxMultiplicity() >= item.getMinMultiplicity()))
.failOn(DescriptionTemplatePersist._maxMultiplicity).failWith(messageSource.getMessage("Validation.LowerThanMin", new Object[]{DescriptionTemplatePersist._minMultiplicity}, LocaleContextHolder.getLocale()))
); );
} }
} }

View File

@ -149,9 +149,6 @@ public class SectionPersist {
this.spec() this.spec()
.must(() -> !this.isNull(item.getHasTemplates())) .must(() -> !this.isNull(item.getHasTemplates()))
.failOn(SectionPersist._hasTemplates).failWith(messageSource.getMessage("Validation_Required", new Object[]{SectionPersist._hasTemplates}, LocaleContextHolder.getLocale())), .failOn(SectionPersist._hasTemplates).failWith(messageSource.getMessage("Validation_Required", new Object[]{SectionPersist._hasTemplates}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isListNullOrEmpty(item.getFields()))
.failOn(SectionPersist._fields).failWith(messageSource.getMessage("Validation_Required", new Object[]{SectionPersist._fields}, LocaleContextHolder.getLocale())),
this.navSpec() this.navSpec()
.iff(() -> !this.isListNullOrEmpty(item.getFields())) .iff(() -> !this.isListNullOrEmpty(item.getFields()))
.on(SectionPersist._fields) .on(SectionPersist._fields)

View File

@ -25,3 +25,4 @@ Validation.LowerThanMin= value must be equal or larger than {0}
Validation.LessThenEqual= value {0} must be equal or less than {1} Validation.LessThenEqual= value {0} must be equal or less than {1}
Validation.LargerThenEqual= value {0} must be equal or larger than {1} Validation.LargerThenEqual= value {0} must be equal or larger than {1}
Validation.MissingFields= missing fields: {0} Validation.MissingFields= missing fields: {0}
Validation.InvalidDescriptionTemplateMultiplicity= {0} can not be used

View File

@ -295,7 +295,6 @@ export class DmpBlueprintEditorComponent extends BaseEditor<DmpBlueprintEditorMo
addSection(): void { addSection(): void {
const formArray = this.formGroup.get('definition').get('sections') as FormArray; const formArray = this.formGroup.get('definition').get('sections') as FormArray;
formArray.push(this.editorModel.createChildSection(formArray.length)); formArray.push(this.editorModel.createChildSection(formArray.length));
this.addField(formArray.length - 1);
} }
removeSection(sectionIndex: number): void { removeSection(sectionIndex: number): void {

View File

@ -247,7 +247,7 @@ export class DmpBlueprintDefinitionSectionEditorModel implements DmpBlueprintDef
baseValidationArray.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}ordinal`)] }); baseValidationArray.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}ordinal`)] });
baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}description`)] }); baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}description`)] });
baseValidationArray.push({ key: 'hasTemplates', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}hasTemplates`)] }); baseValidationArray.push({ key: 'hasTemplates', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}hasTemplates`)] });
baseValidationArray.push({ key: 'fields', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}fields`)] }); baseValidationArray.push({ key: 'fields', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fields`)] });
baseValidationArray.push({ key: 'descriptionTemplates', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}descriptionTemplates`)] }); baseValidationArray.push({ key: 'descriptionTemplates', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}descriptionTemplates`)] });
baseValidationArray.push({ key: 'prefillingSourcesIds', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}prefillingSourcesIds`)] }); baseValidationArray.push({ key: 'prefillingSourcesIds', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}prefillingSourcesIds`)] });
baseValidationArray.push({ key: 'hash', validators: [] }); baseValidationArray.push({ key: 'hash', validators: [] });

View File

@ -57,7 +57,7 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist {
})); }));
}); });
} else if (section.descriptionTemplates?.length > 0) { } else if (section.descriptionTemplates?.length > 0) {
sectionTempaltesFromDmp.forEach(blueprintDefinedDescriptionTemplate => { section.descriptionTemplates.forEach(blueprintDefinedDescriptionTemplate => {
this.descriptionTemplates.push(new DmpDescriptionTemplateEditorModel(this.validationErrorModel).fromModel( this.descriptionTemplates.push(new DmpDescriptionTemplateEditorModel(this.validationErrorModel).fromModel(
{ {
sectionId: section.id, sectionId: section.id,