From 4b9b5cc0563679aa9f203d8815c96a50e3518ceb Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Fri, 12 Jan 2024 15:00:34 +0200 Subject: [PATCH] dmp reference changes --- .../types/dmp/DmpBlueprintValueEntity.java | 8 +- .../dmpreference/DmpReferenceDataEntity.java | 15 ++ .../data/DescriptionReferenceEntity.java | 15 +- .../java/eu/eudat/model/DmpReference.java | 24 +-- .../model/builder/DmpReferenceBuilder.java | 19 ++- .../dmpreference/DmpReferenceDataBuilder.java | 56 +++++++ .../model/censorship/DmpReferenceCensor.java | 4 +- .../dmpreference/DmpReferenceDataCensor.java | 42 +++++ .../model/dmpreference/DmpReferenceData.java | 16 ++ .../eu/eudat/model/persist/DmpPersist.java | 23 +-- .../model/persist/DmpReferencePersist.java | 50 ++---- .../DmpBlueprintValuePersist.java | 53 +++++-- .../dmpreference/DmpReferenceDataPersist.java | 59 +++++++ .../eu/eudat/query/DmpReferenceQuery.java | 1 - .../eu/eudat/service/dmp/DmpServiceImpl.java | 149 +++++++++++------- .../reference/ReferenceServiceImpl.java | 3 +- .../controllers/v2/ReferenceController.java | 4 +- 17 files changed, 385 insertions(+), 156 deletions(-) create mode 100644 dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpreference/DmpReferenceDataEntity.java create mode 100644 dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpreference/DmpReferenceDataBuilder.java create mode 100644 dmp-backend/core/src/main/java/eu/eudat/model/censorship/dmpreference/DmpReferenceDataCensor.java create mode 100644 dmp-backend/core/src/main/java/eu/eudat/model/dmpreference/DmpReferenceData.java create mode 100644 dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpreference/DmpReferenceDataPersist.java diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmp/DmpBlueprintValueEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmp/DmpBlueprintValueEntity.java index f0158df3c..4a08f79a3 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmp/DmpBlueprintValueEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmp/DmpBlueprintValueEntity.java @@ -1,16 +1,18 @@ package eu.eudat.commons.types.dmp; +import java.util.UUID; + public class DmpBlueprintValueEntity { - private String fieldId; + private UUID fieldId; private String value; - public String getFieldId() { + public UUID getFieldId() { return fieldId; } - public void setFieldId(String fieldId) { + public void setFieldId(UUID fieldId) { this.fieldId = fieldId; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpreference/DmpReferenceDataEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpreference/DmpReferenceDataEntity.java new file mode 100644 index 000000000..d488b4a1c --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpreference/DmpReferenceDataEntity.java @@ -0,0 +1,15 @@ +package eu.eudat.commons.types.dmpreference; + +import java.util.UUID; + +public class DmpReferenceDataEntity { + private UUID blueprintFieldId; + + public UUID getBlueprintFieldId() { + return blueprintFieldId; + } + + public void setBlueprintFieldId(UUID blueprintFieldId) { + this.blueprintFieldId = blueprintFieldId; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java index a3d13f7f0..748955a22 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java @@ -18,10 +18,10 @@ public class DescriptionReferenceEntity extends TenantScopedBaseEntity { public static final String _id = "id"; -// @Column(name = "data") -// private String data; -// -// public static final String _data = "data"; + @Column(name = "data") + private String data; + + public static final String _data = "data"; @Column(name = "description_id", columnDefinition = "uuid", nullable = false) private UUID descriptionId; @@ -97,4 +97,11 @@ public class DescriptionReferenceEntity extends TenantScopedBaseEntity { this.isActive = isActive; } + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/DmpReference.java b/dmp-backend/core/src/main/java/eu/eudat/model/DmpReference.java index cc9237f1e..b29f6a535 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/DmpReference.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/DmpReference.java @@ -1,5 +1,7 @@ package eu.eudat.model; +import eu.eudat.model.dmpreference.DmpReferenceData; + import java.time.Instant; import java.util.UUID; @@ -14,9 +16,6 @@ public class DmpReference { private Reference reference; public static final String _reference = "reference"; - private String data; - public static final String _data = "data"; - private Instant createdAt; public static final String _createdAt = "createdAt"; @@ -27,6 +26,9 @@ public class DmpReference { public final static String _hash = "hash"; private String hash; + private DmpReferenceData data; + public static final String _data = "data"; + public UUID getId() { return id; } @@ -51,14 +53,6 @@ public class DmpReference { this.reference = reference; } - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - public Instant getCreatedAt() { return createdAt;} public void setCreatedAt(Instant createdAt) {this.createdAt = createdAt;} @@ -74,4 +68,12 @@ public class DmpReference { public void setHash(String hash) { this.hash = hash; } + + public void setData(DmpReferenceData data) { + this.data = data; + } + + public DmpReferenceData getData() { + return data; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/DmpReferenceBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/DmpReferenceBuilder.java index 0c8f70963..94440d537 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/builder/DmpReferenceBuilder.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/DmpReferenceBuilder.java @@ -1,12 +1,17 @@ package eu.eudat.model.builder; import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.commons.JsonHandlingService; +import eu.eudat.commons.types.description.PropertyDefinitionEntity; +import eu.eudat.commons.types.dmpreference.DmpReferenceDataEntity; import eu.eudat.convention.ConventionService; import eu.eudat.data.DmpReferenceEntity; +import eu.eudat.model.Description; import eu.eudat.model.Dmp; -import eu.eudat.model.DmpDescriptionTemplate; import eu.eudat.model.DmpReference; import eu.eudat.model.Reference; +import eu.eudat.model.builder.descriptionpropertiesdefinition.PropertyDefinitionBuilder; +import eu.eudat.model.builder.dmpreference.DmpReferenceDataBuilder; import eu.eudat.query.DmpQuery; import eu.eudat.query.ReferenceQuery; import gr.cite.tools.data.builder.BuilderFactory; @@ -32,16 +37,18 @@ public class DmpReferenceBuilder extends BaseBuilder authorize = EnumSet.of(AuthorizationFlags.None); @Autowired public DmpReferenceBuilder( - ConventionService conventionService, - BuilderFactory builderFactory, QueryFactory queryFactory) { + ConventionService conventionService, + BuilderFactory builderFactory, QueryFactory queryFactory, JsonHandlingService jsonHandlingService) { super(conventionService, new LoggerService(LoggerFactory.getLogger(DmpReferenceBuilder.class))); this.builderFactory = builderFactory; this.queryFactory = queryFactory; + this.jsonHandlingService = jsonHandlingService; } public DmpReferenceBuilder authorize(EnumSet values) { @@ -62,16 +69,20 @@ public class DmpReferenceBuilder extends BaseBuilder dmpItemsMap = this.collectDmps(dmpFields, data); + FieldSet dataFields = fields.extractPrefixed(this.asPrefix(DmpReference._data)); List models = new ArrayList<>(); for (DmpReferenceEntity d : data) { DmpReference m = new DmpReference(); if (fields.hasField(this.asIndexer(DmpReference._id))) m.setId(d.getId()); - if (fields.hasField(this.asIndexer(DmpReference._data))) m.setData(d.getData()); if (fields.hasField(this.asIndexer(DmpReference._createdAt))) m.setCreatedAt(d.getCreatedAt()); if (fields.hasField(this.asIndexer(DmpReference._updatedAt))) m.setUpdatedAt(d.getUpdatedAt()); if (fields.hasField(this.asIndexer(DmpReference._hash))) m.setHash(this.hashValue(d.getUpdatedAt())); if (!referenceFields.isEmpty() && referenceItemsMap != null && referenceItemsMap.containsKey(d.getReferenceId())) m.setReference(referenceItemsMap.get(d.getReferenceId())); if (!dmpFields.isEmpty() && dmpItemsMap != null && dmpItemsMap.containsKey(d.getDmpId())) m.setDmp(dmpItemsMap.get(d.getDmpId())); + if (!dataFields.isEmpty() && d.getData() != null){ + DmpReferenceDataEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(DmpReferenceDataEntity.class, d.getData()); + m.setData(this.builderFactory.builder(DmpReferenceDataBuilder.class).authorize(this.authorize).build(dataFields, propertyDefinition)); + } models.add(m); } this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpreference/DmpReferenceDataBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpreference/DmpReferenceDataBuilder.java new file mode 100644 index 000000000..43ed8c70f --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpreference/DmpReferenceDataBuilder.java @@ -0,0 +1,56 @@ +package eu.eudat.model.builder.dmpreference; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.commons.types.dmpreference.DmpReferenceDataEntity; +import eu.eudat.convention.ConventionService; +import eu.eudat.model.builder.BaseBuilder; +import eu.eudat.model.dmpreference.DmpReferenceData; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component("referencedmpreferencedatabuilder") +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class DmpReferenceDataBuilder extends BaseBuilder { + + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public DmpReferenceDataBuilder( + ConventionService conventionService) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(DmpReferenceDataBuilder.class))); + } + + public DmpReferenceDataBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + //Not Bulk Build because is XML no interaction with db + + List models = new ArrayList<>(); + for (DmpReferenceDataEntity d : data) { + DmpReferenceData m = new DmpReferenceData(); + if (fields.hasField(this.asIndexer(DmpReferenceData._blueprintFieldId))) m.setBlueprintFieldId(d.getBlueprintFieldId()); + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpReferenceCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpReferenceCensor.java index c46c5d225..02a286b01 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpReferenceCensor.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpReferenceCensor.java @@ -2,8 +2,8 @@ package eu.eudat.model.censorship; import eu.eudat.authorization.Permission; import eu.eudat.convention.ConventionService; -import eu.eudat.model.DmpDescriptionTemplate; import eu.eudat.model.DmpReference; +import eu.eudat.model.censorship.dmpreference.DmpReferenceDataCensor; import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.data.censor.CensorFactory; import gr.cite.tools.fieldset.FieldSet; @@ -43,6 +43,8 @@ public class DmpReferenceCensor extends BaseCensor { this.censorFactory.censor(DmpCensor.class).censor(dmpFields, userId); FieldSet templateFields = fields.extractPrefixed(this.asIndexerPrefix(DmpReference._reference)); this.censorFactory.censor(ReferenceCensor.class).censor(templateFields, userId); + FieldSet dataFields = fields.extractPrefixed(this.asIndexerPrefix(DmpReference._data)); + this.censorFactory.censor(DmpReferenceDataCensor.class).censor(dataFields, userId); } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/dmpreference/DmpReferenceDataCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/dmpreference/DmpReferenceDataCensor.java new file mode 100644 index 000000000..6c90f9992 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/dmpreference/DmpReferenceDataCensor.java @@ -0,0 +1,42 @@ +package eu.eudat.model.censorship.dmpreference; + +import eu.eudat.authorization.Permission; +import eu.eudat.convention.ConventionService; +import eu.eudat.model.censorship.BaseCensor; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class DmpReferenceDataCensor extends BaseCensor { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpReferenceDataCensor.class)); + + protected final AuthorizationService authService; + + + @Autowired + public DmpReferenceDataCensor(ConventionService conventionService, + AuthorizationService authService) { + super(conventionService); + this.authService = authService; + } + + public void censor(FieldSet fields, UUID userId) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (fields == null || fields.isEmpty()) + return; + + this.authService.authorizeForce(Permission.BrowseDmpDescriptionTemplate); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/dmpreference/DmpReferenceData.java b/dmp-backend/core/src/main/java/eu/eudat/model/dmpreference/DmpReferenceData.java new file mode 100644 index 000000000..ef04104f6 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/dmpreference/DmpReferenceData.java @@ -0,0 +1,16 @@ +package eu.eudat.model.dmpreference; + +import java.util.UUID; + +public class DmpReferenceData { + private UUID blueprintFieldId; + public final static String _blueprintFieldId = "blueprintFieldId"; + + public UUID getBlueprintFieldId() { + return blueprintFieldId; + } + + public void setBlueprintFieldId(UUID blueprintFieldId) { + this.blueprintFieldId = blueprintFieldId; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java index 9e3070d81..51cbe2720 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java @@ -45,9 +45,9 @@ public class DmpPersist { private DmpAccessType accessType; - private List references; - - public static final String _references = "references"; +// private List references; +// +// public static final String _references = "references"; private List descriptionTemplates; @@ -105,14 +105,6 @@ public class DmpPersist { this.language = language; } - public List getReferences() { - return references; - } - - public void setReferences(List references) { - this.references = references; - } - public UUID getBlueprint() { return blueprint; } @@ -201,15 +193,6 @@ public class DmpPersist { .on(DmpPersist._properties) .over(item.getProperties()) .using(() -> this.validatorFactory.validator(DmpPropertiesPersist.DmpPropertiesPersistValidator.class).setStatus(item.getStatus())), - this.spec() - .iff(() -> item.getStatus() == DmpStatus.Finalized) - .must(() -> !this.isNull(item.getReferences())) - .failOn(DmpPersist._references).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpPersist._references}, LocaleContextHolder.getLocale())), - this.navSpec() - .iff(() -> !this.isNull(item.getReferences())) - .on(DmpPersist._references) - .over(item.getReferences()) - .using(() -> this.validatorFactory.validator(DmpReferencePersist.DmpReferencePersistValidator.class)), this.spec() .iff(() -> item.getStatus() == DmpStatus.Finalized) .must(() -> !this.isNull(item.getDescriptionTemplates())) diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpReferencePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpReferencePersist.java index cee1cb94b..353a063df 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpReferencePersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpReferencePersist.java @@ -5,6 +5,7 @@ import eu.eudat.commons.validation.ValidatorFactory; import eu.eudat.commons.validation.specification.Specification; import eu.eudat.convention.ConventionService; import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.model.persist.dmpreference.DmpReferenceDataPersist; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Scope; @@ -17,27 +18,15 @@ import java.util.UUID; public class DmpReferencePersist { - private UUID id; - private ReferencePersist reference; public static final String _reference = "reference"; - private String data; + + private DmpReferenceDataPersist data; public static final String _data = "data"; - private String hash; - - public static final String _hash = "hash"; - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } public ReferencePersist getReference() { return reference; @@ -47,22 +36,14 @@ public class DmpReferencePersist { this.reference = reference; } - public String getData() { + public DmpReferenceDataPersist getData() { return data; } - public void setData(String data) { + public void setData(DmpReferenceDataPersist data) { this.data = data; } - public String getHash() { - return hash; - } - - public void setHash(String hash) { - this.hash = hash; - } - @Component(DmpReferencePersistValidator.ValidatorName) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public static class DmpReferencePersistValidator extends BaseValidator { @@ -87,26 +68,25 @@ public class DmpReferencePersist { @Override protected List specifications(DmpReferencePersist item) { return Arrays.asList( - this.spec() - .iff(() -> this.isValidGuid(item.getId())) - .must(() -> this.isValidHash(item.getHash())) - .failOn(DmpReferencePersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpReferencePersist._hash}, LocaleContextHolder.getLocale())), - this.spec() - .iff(() -> !this.isValidGuid(item.getId())) - .must(() -> !this.isValidHash(item.getHash())) - .failOn(DmpReferencePersist._hash).failWith(messageSource.getMessage("Validation_OverPosting", new Object[]{}, LocaleContextHolder.getLocale())), this.spec() .must(() -> !this.isNull(item.getData())) .failOn(DmpReferencePersist._data).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpReferencePersist._data}, LocaleContextHolder.getLocale())), - this.spec() .must(() -> !this.isNull(item.getReference())) - .failOn(DmpReferencePersist._reference).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())), + .failOn(DmpReferencePersist._reference).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpReferencePersist._reference}, LocaleContextHolder.getLocale())), this.refSpec() .iff(() -> !this.isNull(item.getReference())) .on(DmpReferencePersist._reference) .over(item.getReference()) - .using(() -> this.validatorFactory.validator(ReferencePersist.ReferencePersistValidator.class)) + .using(() -> this.validatorFactory.validator(ReferencePersist.ReferencePersistValidator.class)), + this.spec() + .must(() -> !this.isNull(item.getData())) + .failOn(DmpReferencePersist._data).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpReferencePersist._data}, LocaleContextHolder.getLocale())), + this.refSpec() + .iff(() -> !this.isNull(item.getData())) + .on(DmpReferencePersist._data) + .over(item.getData()) + .using(() -> this.validatorFactory.validator(DmpReferenceDataPersist.DmpReferenceDataPersistValidator.class)) ); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java index c15cc9a6a..91a8fa072 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java @@ -4,37 +4,35 @@ import eu.eudat.commons.validation.BaseValidator; import eu.eudat.commons.validation.specification.Specification; import eu.eudat.convention.ConventionService; import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.model.persist.ReferencePersist; import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.MessageSource; import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.UUID; public class DmpBlueprintValuePersist { + private UUID fieldId; - private String fieldId; - - private String fieldName; - + public static final String _fieldId = "fieldId"; private String fieldValue; + public static final String _fieldValue = "fieldValue"; + private List references; + public static final String _references = "references"; - public String getFieldId() { + public UUID getFieldId() { return fieldId; } - public void setFieldId(String fieldId) { + public void setFieldId(UUID fieldId) { this.fieldId = fieldId; } - public String getFieldName() { - return fieldName; - } - - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - public String getFieldValue() { return fieldValue; } @@ -43,14 +41,25 @@ public class DmpBlueprintValuePersist { this.fieldValue = fieldValue; } + public List getReferences() { + return references; + } + + public void setReferences(List references) { + this.references = references; + } + @Component(DmpBlueprintValuePersistValidator.ValidatorName) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public static class DmpBlueprintValuePersistValidator extends BaseValidator { + private final MessageSource messageSource; + public static final String ValidatorName = "DmpBlueprintValuePersistValidator"; - protected DmpBlueprintValuePersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors) { + protected DmpBlueprintValuePersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) { super(conventionService, errors); + this.messageSource = messageSource; } @Override @@ -60,7 +69,19 @@ public class DmpBlueprintValuePersist { @Override protected List specifications(DmpBlueprintValuePersist item) { - return new ArrayList<>(); + return Arrays.asList( + this.spec() + .must(() -> !this.isValidGuid(item.getFieldId())) + .failOn(DmpBlueprintValuePersist._fieldId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpBlueprintValuePersist._fieldId}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> this.isNull(item.getReferences()) || item.getReferences().isEmpty()) + .must(() -> !this.isEmpty(item.getFieldValue())) + .failOn(DmpBlueprintValuePersist._fieldValue).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpBlueprintValuePersist._fieldValue}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> !this.isNull(item.getReferences()) && !item.getReferences().isEmpty()) + .must(() -> this.isEmpty(item.getFieldValue())) + .failOn(DmpBlueprintValuePersist._fieldValue).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{DmpBlueprintValuePersist._fieldValue}, LocaleContextHolder.getLocale())) + ); } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpreference/DmpReferenceDataPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpreference/DmpReferenceDataPersist.java new file mode 100644 index 000000000..12353ba8b --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpreference/DmpReferenceDataPersist.java @@ -0,0 +1,59 @@ +package eu.eudat.model.persist.dmpreference; + +import eu.eudat.commons.validation.BaseValidator; +import eu.eudat.commons.validation.specification.Specification; +import eu.eudat.convention.ConventionService; +import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.model.persist.ReferencePersist; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class DmpReferenceDataPersist { + + private UUID blueprintFieldId; + + public static final String _blueprintFieldId = "blueprintFieldId"; + + public UUID getBlueprintFieldId() { + return blueprintFieldId; + } + + public void setBlueprintFieldId(UUID blueprintFieldId) { + this.blueprintFieldId = blueprintFieldId; + } + + @Component(DmpReferenceDataPersistValidator.ValidatorName) + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class DmpReferenceDataPersistValidator extends BaseValidator { + + public static final String ValidatorName = "DmpReferenceDataPersistValidator"; + private final MessageSource messageSource; + + protected DmpReferenceDataPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) { + super(conventionService, errors); + this.messageSource = messageSource; + } + + @Override + protected Class modelClass() { + return DmpReferenceDataPersist.class; + } + + @Override + protected List specifications(DmpReferenceDataPersist item) { + return Arrays.asList( + this.spec() + .must(() -> !this.isNull(item.getBlueprintFieldId())) + .failOn(DmpReferenceDataPersist._blueprintFieldId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpReferenceDataPersist._blueprintFieldId}, LocaleContextHolder.getLocale())) + ); + } + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/DmpReferenceQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/DmpReferenceQuery.java index 546aead03..ebe690b8f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/DmpReferenceQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/DmpReferenceQuery.java @@ -4,7 +4,6 @@ import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.data.DescriptionEntity; import eu.eudat.data.DmpEntity; import eu.eudat.data.DmpReferenceEntity; import eu.eudat.data.ReferenceEntity; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java index d3706f62f..9bc67e78f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java @@ -12,6 +12,7 @@ import eu.eudat.commons.types.actionconfirmation.DmpInvitationEntity; import eu.eudat.commons.types.dmp.DmpBlueprintValueEntity; import eu.eudat.commons.types.dmp.DmpContactEntity; import eu.eudat.commons.types.dmp.DmpPropertiesEntity; +import eu.eudat.commons.types.dmpreference.DmpReferenceDataEntity; import eu.eudat.commons.types.notification.*; import eu.eudat.commons.types.reference.DefinitionEntity; import eu.eudat.commons.types.reference.FieldEntity; @@ -37,6 +38,7 @@ import eu.eudat.model.persist.actionconfirmation.DmpInvitationPersist; import eu.eudat.model.persist.dmpproperties.DmpBlueprintValuePersist; import eu.eudat.model.persist.dmpproperties.DmpContactPersist; import eu.eudat.model.persist.dmpproperties.DmpPropertiesPersist; +import eu.eudat.model.persist.dmpreference.DmpReferenceDataPersist; import eu.eudat.model.persist.referencedefinition.DefinitionPersist; import eu.eudat.model.persist.referencedefinition.FieldPersist; import eu.eudat.query.*; @@ -159,7 +161,7 @@ public class DmpServiceImpl implements DmpService { DmpEntity data = this.patchAndSave(model); - this.patchAndSaveReferences(model.getReferences(), data.getId()); + this.patchAndSaveReferences(this.buildDmpReferencePersists(model.getProperties()), data.getId()); this.patchAndSaveTemplates(data.getId(), model.getDescriptionTemplates()); @@ -250,7 +252,7 @@ public class DmpServiceImpl implements DmpService { List latestVersionDmps = latestVersionDmpEntityQuery.collect(); if (latestVersionDmps.isEmpty()) throw new MyValidationException("Previous dmp not found"); if (latestVersionDmps.size() > 1) throw new MyValidationException("Multiple previous dmps found"); - if (!latestVersionDmps.get(0).getVersion().equals(oldDmpEntity.getVersion())){ + if (!latestVersionDmps.getFirst().getVersion().equals(oldDmpEntity.getVersion())){ throw new MyValidationException(this.errors.getDmpNewVersionConflict().getCode(), this.errors.getDmpNewVersionConflict().getMessage()); } @@ -490,9 +492,8 @@ public class DmpServiceImpl implements DmpService { @Override public ResponseEntity export(UUID id, String exportType) throws InvalidApplicationException, IOException { HttpHeaders headers = new HttpHeaders(); - String type = exportType; - FileEnvelope fileEnvelope = this.fileTransformerService.exportDmp(id, type); + FileEnvelope fileEnvelope = this.fileTransformerService.exportDmp(id, exportType); headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename()); byte[] data = Files.readAllBytes(fileEnvelope.getFile().toPath()); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); @@ -563,7 +564,7 @@ public class DmpServiceImpl implements DmpService { if (!this.conventionService.isListNullOrEmpty(persist.getDmpBlueprintValues())){ data.setDmpBlueprintValues(new ArrayList<>()); for (DmpBlueprintValuePersist fieldValuePersist: persist.getDmpBlueprintValues()) { - data.getDmpBlueprintValues().add(this.buildDmpBlueprintValueEntity(fieldValuePersist)); + if (!this.conventionService.isNullOrEmpty(fieldValuePersist.getFieldValue())) data.getDmpBlueprintValues().add(this.buildDmpBlueprintValueEntity(fieldValuePersist)); } } return data; @@ -591,71 +592,98 @@ public class DmpServiceImpl implements DmpService { return data; } + + + private @NotNull List buildDmpReferencePersists(DmpPropertiesPersist persist){ + List dmpReferencePersists = new ArrayList<>(); + if (!this.conventionService.isListNullOrEmpty(persist.getDmpBlueprintValues())){ + for (DmpBlueprintValuePersist fieldValuePersist: persist.getDmpBlueprintValues()) { + if (this.conventionService.isNullOrEmpty(fieldValuePersist.getFieldValue()) && !this.conventionService.isListNullOrEmpty( fieldValuePersist.getReferences())) { + for (ReferencePersist referencePersist : fieldValuePersist.getReferences()) { + DmpReferencePersist dmpReferencePersist = new DmpReferencePersist(); + dmpReferencePersist.setData(new DmpReferenceDataPersist()); + dmpReferencePersist.getData().setBlueprintFieldId(fieldValuePersist.getFieldId()); + dmpReferencePersist.setReference(referencePersist); + } + } + } + } + return dmpReferencePersists; + } + private void patchAndSaveReferences(List models, UUID dmpId) throws InvalidApplicationException { - if (models == null || models.isEmpty()) - return; + if (models == null) models = new ArrayList<>(); - List references = this.queryFactory.query(DmpReferenceQuery.class).dmpIds(dmpId).collect(); - Map> referencesLookup = this.conventionService.toDictionaryOfList(references, DmpReferenceEntity::getDmpId); - - List existingReferences; - if (referencesLookup.containsKey(dmpId)) - existingReferences = this.queryFactory.query(ReferenceQuery.class).ids(referencesLookup.get(dmpId).stream().map(DmpReferenceEntity::getId).toList()).collect(); - else - existingReferences = new ArrayList<>(); + List dmpReferences = this.queryFactory.query(DmpReferenceQuery.class).dmpIds(dmpId).collect(); + Map> dmpReferenceEntityByReferenceId = new HashMap<>(); + for (DmpReferenceEntity dmpReferenceEntity : dmpReferences){ + List dmpReferenceEntities = dmpReferenceEntityByReferenceId.getOrDefault(dmpReferenceEntity.getReferenceId(), null); + if (dmpReferenceEntities == null) { + dmpReferenceEntities = new ArrayList<>(); + dmpReferenceEntityByReferenceId.put(dmpReferenceEntity.getReferenceId(), dmpReferenceEntities); + } + dmpReferenceEntities.add(dmpReferenceEntity); + } - List updatedReferencesIds = models.stream().map(x -> x.getReference().getId()).filter(this.conventionService::isValidGuid).distinct().toList(); - List toDelete = existingReferences.stream().filter(x -> !updatedReferencesIds.contains(x.getId())).toList(); - List dmpReferenceRecordsToDelete = this.queryFactory.query(DmpReferenceQuery.class).referenceIds(toDelete.stream().map(ReferenceEntity::getId).toList()).collect(); - this.deleterFactory.deleter(DmpReferenceDeleter.class).delete(dmpReferenceRecordsToDelete); - - Map existingReferencesLookup = existingReferences.stream().collect(Collectors.toMap(ReferenceEntity::getId, x -> x)); + Map dmpReferenceDataEntityMap = new HashMap<>(); + for (DmpReferenceEntity dmpReferenceEntity : dmpReferences){ + dmpReferenceDataEntityMap.put(dmpReferenceEntity.getDmpId(), this.jsonHandlingService.fromJsonSafe(DmpReferenceDataEntity.class, dmpReferenceEntity.getData())); + } + List updatedCreatedIds = new ArrayList<>(); for (DmpReferencePersist model : models) { - ReferencePersist referenceModel = model.getReference(); - - Boolean isUpdate = this.conventionService.isValidGuid(referenceModel.getId()); - - ReferenceEntity data; - if (isUpdate) { - if (!existingReferencesLookup.containsKey(referenceModel.getId())) - throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{referenceModel.getId(), Reference.class.getSimpleName()}, LocaleContextHolder.getLocale())); - data = existingReferencesLookup.get(referenceModel.getId()); - if (data == null) - throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{referenceModel.getId(), Reference.class.getSimpleName()}, LocaleContextHolder.getLocale())); - if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(referenceModel.getHash())) - throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); + ReferencePersist referencePersist = model.getReference(); + ReferenceEntity referenceEntity = null; + if (this.conventionService.isValidGuid(referencePersist.getId())){ + referenceEntity = this.entityManager.find(ReferenceEntity.class, referencePersist.getId()); + if (referenceEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{referencePersist.getId(), Reference.class.getSimpleName()}, LocaleContextHolder.getLocale())); } else { - data = new ReferenceEntity(); - data.setId(UUID.randomUUID()); - data.setIsActive(IsActive.Active); - data.setCreatedAt(Instant.now()); + referenceEntity = this.queryFactory.query(ReferenceQuery.class).sourceTypes(referencePersist.getSourceType()).references(referencePersist.getReference()).first(); + if (referenceEntity == null){ + referenceEntity = new ReferenceEntity(); + referenceEntity.setId(UUID.randomUUID()); + referenceEntity.setIsActive(IsActive.Active); + referenceEntity.setCreatedAt(Instant.now()); - DmpReferenceEntity dmpReference = new DmpReferenceEntity(); - dmpReference.setReferenceId(data.getId()); - dmpReference.setDmpId(dmpId); - dmpReference.setCreatedAt(Instant.now()); - dmpReference.setUpdatedAt(Instant.now()); - dmpReference.setIsActive(IsActive.Active); - dmpReference.setData(model.getData()); - this.entityManager.persist(dmpReference); + referenceEntity.setDefinition(this.xmlHandlingService.toXmlSafe(this.buildDefinitionEntity(referencePersist.getDefinition()))); + referenceEntity.setUpdatedAt(Instant.now()); + referenceEntity.setReference(referencePersist.getReference()); + referenceEntity.setAbbreviation(referencePersist.getAbbreviation()); + referenceEntity.setSource(referencePersist.getSource()); + referenceEntity.setSourceType(referencePersist.getSourceType()); + this.entityManager.persist(referenceEntity); + } } - data.setDefinition(this.xmlHandlingService.toXmlSafe(this.buildDefinitionEntity(referenceModel.getDefinition()))); + DmpReferenceEntity data = null; + List dmpReferenceEntities = dmpReferenceEntityByReferenceId.getOrDefault(referenceEntity.getId(), new ArrayList<>()); + for (DmpReferenceEntity dmpReferenceEntity : dmpReferenceEntities){ + DmpReferenceDataEntity dmpReferenceDataEntity = dmpReferenceDataEntityMap.getOrDefault(dmpReferenceEntity.getId(), new DmpReferenceDataEntity()); + if (Objects.equals(dmpReferenceDataEntity.getBlueprintFieldId(), model.getData().getBlueprintFieldId())){ + data = dmpReferenceEntity; + break; + } + } + boolean isUpdate = data != null; + + if (!isUpdate) { + data = new DmpReferenceEntity(); + data.setReferenceId(referenceEntity.getId()); + data.setDmpId(dmpId); + data.setCreatedAt(Instant.now()); + data.setIsActive(IsActive.Active); + data.setData(this.jsonHandlingService.toJsonSafe(this.buildDmpReferenceDataEntity(model.getData()))); + } + updatedCreatedIds.add(data.getId()); + data.setUpdatedAt(Instant.now()); - data.setReference(referenceModel.getReference()); - data.setAbbreviation(referenceModel.getAbbreviation()); - data.setSource(referenceModel.getSource()); - data.setSourceType(referenceModel.getSourceType()); - - if (isUpdate) - this.entityManager.merge(data); - else - this.entityManager.persist(data); + if (isUpdate) this.entityManager.merge(data); + else this.entityManager.persist(data); } + List toDelete = dmpReferences.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList()); + this.deleterFactory.deleter(DmpReferenceDeleter.class).delete(toDelete); this.entityManager.flush(); - } @@ -695,6 +723,13 @@ public class DmpServiceImpl implements DmpService { return data; } + private @NotNull DmpReferenceDataEntity buildDmpReferenceDataEntity(DmpReferenceDataPersist persist){ + DmpReferenceDataEntity data = new DmpReferenceDataEntity(); + if (persist == null) return data; + data.setBlueprintFieldId(persist.getBlueprintFieldId()); + return data; + } + private @NotNull FieldEntity buildDmpContactEntity(FieldPersist persist){ FieldEntity data = new FieldEntity(); if (persist == null) return data; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java index 9b76c999f..e9aa2f0a4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java @@ -9,6 +9,7 @@ import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.ReferenceSourceType; import eu.eudat.commons.enums.ReferenceTypeExternalApiHTTPMethodType; import eu.eudat.commons.enums.ReferenceTypeSourceType; import eu.eudat.commons.exceptions.HugeResultSetException; @@ -223,7 +224,7 @@ public class ReferenceServiceImpl implements ReferenceService { } private List fetchFromDb(ReferenceSearchLookup lookup){ - ReferenceQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic); + ReferenceQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).sourceTypes(ReferenceSourceType.Internal); List data = query.collectAs(lookup.getProject()); return this.builderFactory.builder(ReferenceBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(lookup.getProject(), data); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java index 71426a411..ab0059fdf 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java @@ -68,7 +68,6 @@ public class ReferenceController extends BaseController { private final MessageSource messageSource; - private final AuthorizationService authorizationService; @Autowired public ReferenceController( @@ -78,7 +77,7 @@ public class ReferenceController extends BaseController { AuditService auditService, CensorFactory censorFactory, QueryFactory queryFactory, - MessageSource messageSource, AuthorizationService authorizationService) { + MessageSource messageSource) { super(apiContext); this.builderFactory = builderFactory; this.referenceService = referenceService; @@ -86,7 +85,6 @@ public class ReferenceController extends BaseController { this.censorFactory = censorFactory; this.queryFactory = queryFactory; this.messageSource = messageSource; - this.authorizationService = authorizationService; } @PostMapping("query")