dmp version add not finalized

This commit is contained in:
Efstratios Giannopoulos 2024-03-21 12:12:12 +02:00
parent 0dffbec480
commit e61f1afaf5
5 changed files with 144 additions and 43 deletions

View File

@ -7,7 +7,9 @@ import java.util.Map;
public enum DmpVersionStatus implements DatabaseEnum<Short> {
Current((short) 0), Previous ((short) 1);
Current((short) 0),
Previous((short) 1),
NotFinalized((short) 2);
private final Short value;

View File

@ -1,5 +1,7 @@
package eu.eudat.model.deleter;
import eu.eudat.commons.enums.DescriptionTemplateVersionStatus;
import eu.eudat.commons.enums.DmpVersionStatus;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.data.DescriptionTemplateEntity;
import eu.eudat.data.DmpDescriptionTemplateEntity;
@ -11,6 +13,7 @@ import eu.eudat.query.UserDescriptionTemplateQuery;
import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.persistence.EntityManager;
@ -91,6 +94,7 @@ public class DescriptionTemplateDeleter implements Deleter {
for (DescriptionTemplateEntity item : data) {
logger.trace("deleting item {}", item.getId());
if(item.getVersionStatus().equals(DescriptionTemplateVersionStatus.Current)) throw new MyApplicationException("Description is current can not deleted");
item.setIsActive(IsActive.Inactive);
item.setUpdatedAt(now);
logger.trace("updating item");

View File

@ -1,5 +1,9 @@
package eu.eudat.model.deleter;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.enums.DmpStatus;
import eu.eudat.commons.enums.DmpVersionStatus;
import eu.eudat.commons.enums.EntityType;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.data.*;
import eu.eudat.model.Description;
@ -10,6 +14,7 @@ import eu.eudat.service.elastic.ElasticService;
import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.persistence.EntityManager;
@ -101,6 +106,9 @@ public class DmpDeleter implements Deleter {
for (DmpEntity item : data) {
logger.trace("deleting item {}", item.getId());
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).types(EntityType.DMP).entityIds(item.getId());
if (entityDoiQuery.count() > 0) throw new MyApplicationException("DMP is deposited can not deleted");
if(item.getVersionStatus().equals(DmpVersionStatus.Current)) throw new MyApplicationException("DMP is current can not deleted");
item.setIsActive(IsActive.Inactive);
item.setUpdatedAt(now);
logger.trace("updating item");

View File

@ -35,7 +35,6 @@ import eu.eudat.query.*;
import eu.eudat.service.fielddatahelper.FieldDataHelperService;
import eu.eudat.service.fielddatahelper.FieldDataHelperServiceProvider;
import eu.eudat.service.responseutils.ResponseUtilsService;
import eu.eudat.service.storage.StorageFileService;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
@ -106,7 +105,6 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
private final ResponseUtilsService responseUtilsService;
private final StorageFileService storageFileService;
private final JsonHandlingService jsonHandlingService;
@ -129,7 +127,6 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
QueryFactory queryFactory, ErrorThesaurusProperties errors,
TenantScope tenantScope,
ResponseUtilsService responseUtilsService,
StorageFileService storageFileService,
JsonHandlingService jsonHandlingService,
NotifyIntegrationEventHandler eventHandler,
NotificationProperties notificationProperties,
@ -147,7 +144,6 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
this.errors = errors;
this.tenantScope = tenantScope;
this.responseUtilsService = responseUtilsService;
this.storageFileService = storageFileService;
this.jsonHandlingService = jsonHandlingService;
this.eventHandler = eventHandler;
this.notificationProperties = notificationProperties;
@ -454,7 +450,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
List<UUID> referenceIds = new ArrayList<>();
for (ReferencePersist model : models) {
ReferenceEntity data = null;
ReferenceEntity data;
if (this.conventionService.isValidGuid(model.getId())){
data = this.entityManager.find(ReferenceEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Reference.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -551,6 +547,27 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
this.authorizationService.authorizeForce(Permission.DeleteDescriptionTemplate);
DescriptionTemplateEntity data = this.entityManager.find(DescriptionTemplateEntity.class, id);
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (data.getVersionStatus().equals(DescriptionTemplateVersionStatus.Current)){
DescriptionTemplateQuery descriptionTemplateQuery = this.queryFactory.query(DescriptionTemplateQuery.class)
.statuses(DescriptionTemplateStatus.Finalized)
.excludedIds(data.getId())
.isActive(IsActive.Active)
.groupIds(data.getGroupId());
descriptionTemplateQuery.setOrder(new Ordering().addDescending(DescriptionTemplate._version));
DescriptionTemplateEntity previousFinalized = descriptionTemplateQuery.first();
if (previousFinalized != null){
previousFinalized.setVersionStatus(DescriptionTemplateVersionStatus.Current);
this.entityManager.merge(previousFinalized);
}
data.setVersionStatus(DescriptionTemplateVersionStatus.NotFinalized);
this.entityManager.merge(data);
this.entityManager.flush();
}
this.deleterFactory.deleter(DescriptionTemplateDeleter.class).deleteAndSaveByIds(List.of(id));
}
@ -640,7 +657,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
//region NewVersion
public DescriptionTemplate createNewVersion(NewVersionDescriptionTemplatePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException {
public DescriptionTemplate createNewVersion(NewVersionDescriptionTemplatePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException {
logger.debug(new MapLogEntry("persisting data descriptionTemplate").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.CreateNewVersionDescriptionTemplate);
@ -864,7 +881,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
//region Export
@Override
public ResponseEntity<byte[]> exportXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, TransformerException, InvalidApplicationException {
public ResponseEntity<byte[]> exportXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException {
logger.debug(new MapLogEntry("persisting data").And("id", id));
this.authorizationService.authorizeForce(Permission.ExportDescriptionTemplate);

View File

@ -58,6 +58,7 @@ import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidatorFactory;
import jakarta.persistence.EntityManager;
import jakarta.xml.bind.JAXBException;
@ -73,8 +74,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.time.Instant;
import java.util.*;
@ -298,23 +297,60 @@ public class DmpServiceImpl implements DmpService {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(id)), Permission.DeleteDmp);
DmpEntity data = this.entityManager.find(DmpEntity.class, id);
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).types(EntityType.DMP).entityIds(data.getId());
if (entityDoiQuery.count() > 0) throw new MyApplicationException("DMP is deposited can not deleted");
DmpEntity previousFinalized = null;
if (data.getVersionStatus().equals(DmpVersionStatus.Current)){
DmpQuery dmpQuery = this.queryFactory.query(DmpQuery.class)
.statuses(DmpStatus.Finalized)
.excludedIds(data.getId())
.isActive(IsActive.Active)
.groupIds(data.getGroupId());
dmpQuery.setOrder(new Ordering().addDescending(Dmp._version));
previousFinalized = dmpQuery.first();
if (previousFinalized != null){
previousFinalized.setVersionStatus(DmpVersionStatus.Current);
this.entityManager.merge(previousFinalized);
}
data.setVersionStatus(DmpVersionStatus.NotFinalized);
this.entityManager.merge(data);
this.entityManager.flush();
}
this.deleterFactory.deleter(DmpDeleter.class).deleteAndSaveByIds(List.of(id), false);
if (previousFinalized != null) this.elasticService.persistDmp(previousFinalized);
}
@Override
public Dmp createNewVersion(NewVersionDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, IOException, TransformerException {
public Dmp createNewVersion(NewVersionDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
logger.debug(new MapLogEntry("persisting data bew version").And("model", model).And("fields", fields));
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation( model.getId())), Permission.CreateNewVersionDmp);
DmpEntity oldDmpEntity = this.entityManager.find(DmpEntity.class, model.getId());
if (oldDmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(oldDmpEntity.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
DmpQuery latestVersionDmpEntityQuery = this.queryFactory.query(DmpQuery.class).groupIds(oldDmpEntity.getGroupId()).versionStatuses(DmpVersionStatus.Current);
List<DmpEntity> latestVersionDmps = latestVersionDmpEntityQuery.collect();
List<DmpEntity> latestVersionDmps = this.queryFactory.query(DmpQuery.class)
.groupIds(oldDmpEntity.getGroupId())
.isActive(IsActive.Active)
.versionStatuses(DmpVersionStatus.Current)
.collect();
if (latestVersionDmps.isEmpty()) throw new MyValidationException("Previous dmp not found");
if (latestVersionDmps.size() > 1) throw new MyValidationException("Multiple previous dmps found");
if (!latestVersionDmps.getFirst().getVersion().equals(oldDmpEntity.getVersion())){
throw new MyValidationException(this.errors.getDmpNewVersionConflict().getCode(), this.errors.getDmpNewVersionConflict().getMessage());
}
Long notFinalizedCount = this.queryFactory.query(DmpQuery.class)
.versionStatuses(DmpVersionStatus.NotFinalized)
.groupIds(oldDmpEntity.getGroupId())
.isActive(IsActive.Active)
.count();
if (notFinalizedCount > 0) throw new MyValidationException("Already created draft for this template");
DmpEntity newDmp = new DmpEntity();
newDmp.setId(UUID.randomUUID());
@ -322,7 +358,7 @@ public class DmpServiceImpl implements DmpService {
newDmp.setCreatedAt(Instant.now());
newDmp.setUpdatedAt(Instant.now());
newDmp.setGroupId(oldDmpEntity.getGroupId());
newDmp.setVersionStatus(DmpVersionStatus.Current);
newDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
newDmp.setVersion((short)(oldDmpEntity.getVersion() + 1));
newDmp.setDescription(model.getDescription());
newDmp.setLabel(model.getLabel());
@ -390,12 +426,11 @@ public class DmpServiceImpl implements DmpService {
this.descriptionService.clone(newDmp.getId(), descriptionId);
}
oldDmpEntity.setVersionStatus(DmpVersionStatus.Previous);
this.entityManager.merge(oldDmpEntity);
this.entityManager.flush();
this.updateVersionStatusAndSave(newDmp, DmpStatus.Draft, newDmp.getStatus());
this.entityManager.flush();
this.elasticService.persistDmp(oldDmpEntity);
this.elasticService.persistDmp(newDmp);
@ -403,6 +438,42 @@ public class DmpServiceImpl implements DmpService {
return this.builderFactory.builder(DmpBuilder.class).build(BaseFieldSet.build(fields, Dmp._id), newDmp);
}
private void updateVersionStatusAndSave(DmpEntity data, DmpStatus previousStatus, DmpStatus newStatus) {
if (previousStatus.equals(newStatus))
return;
if (previousStatus.equals(DmpStatus.Finalized) && newStatus.equals(DmpStatus.Draft)){
boolean alreadyCreatedNewVersion = this.queryFactory.query(DmpQuery.class)
.versionStatuses(DmpVersionStatus.NotFinalized, DmpVersionStatus.Current)
.excludedIds(data.getId())
.isActive(IsActive.Active)
.groupIds(data.getGroupId())
.count() > 0;
if (alreadyCreatedNewVersion) throw new MyValidationException("Already new version is created");
data.setVersionStatus(DmpVersionStatus.NotFinalized);
this.entityManager.merge(data);
}
if (newStatus.equals(DmpStatus.Finalized)) {
List<DmpEntity> latestVersionDmps = this.queryFactory.query(DmpQuery.class)
.versionStatuses(DmpVersionStatus.Current).isActive(IsActive.Active).groupIds(data.getGroupId()).collect();
if (latestVersionDmps.size() > 1)
throw new MyValidationException("Multiple previous template found");
DmpEntity oldDmpEntity = latestVersionDmps.stream().findFirst().orElse(null);
data.setVersionStatus(DmpVersionStatus.Current);
if (oldDmpEntity != null) {
data.setVersion((short) (oldDmpEntity.getVersion() + 1));
oldDmpEntity.setVersionStatus(DmpVersionStatus.Previous);
this.entityManager.merge(oldDmpEntity);
} else {
data.setVersion((short) 1);
}
}
}
@Override
public Dmp buildClone(CloneDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, IOException, InvalidApplicationException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation( model.getId())), Permission.CloneDmp);
@ -418,7 +489,7 @@ public class DmpServiceImpl implements DmpService {
newDmp.setUpdatedAt(Instant.now());
newDmp.setGroupId(UUID.randomUUID());
newDmp.setVersion((short) 1);
newDmp.setVersionStatus(DmpVersionStatus.Current);
newDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
newDmp.setDescription(model.getDescription());
newDmp.setLabel(model.getLabel());
newDmp.setLanguage(existingDmpEntity.getLanguage());
@ -586,12 +657,13 @@ public class DmpServiceImpl implements DmpService {
data.setGroupId(UUID.randomUUID());
data.setVersion((short) 1);
data.setStatus(DmpStatus.Draft);
data.setVersionStatus(DmpVersionStatus.Current);
data.setVersionStatus(DmpVersionStatus.NotFinalized);
data.setCreatorId(userScope.getUserId());
data.setBlueprintId(model.getBlueprint());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
}
DmpStatus previousStatus = data.getStatus();
data.setLabel(model.getLabel());
data.setLanguage(model.getLanguage());
@ -607,6 +679,10 @@ public class DmpServiceImpl implements DmpService {
this.entityManager.flush();
this.updateVersionStatusAndSave(data, previousStatus, data.getStatus());
this.entityManager.flush();
return data;
}
@ -692,7 +768,7 @@ public class DmpServiceImpl implements DmpService {
List<UUID> updatedCreatedIds = new ArrayList<>();
for (DmpReferencePersist model : models) {
ReferencePersist referencePersist = model.getReference();
ReferenceEntity referenceEntity = null;
ReferenceEntity referenceEntity;
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()));
@ -807,15 +883,6 @@ public class DmpServiceImpl implements DmpService {
return data;
}
private DmpUserEntity checkUserRoleIfExists(List<DmpUserEntity> dmpUserEntities, UUID dmp, UUID user, DmpUserRole role) {
for (DmpUserEntity dmpUser : dmpUserEntities) {
if (dmpUser.getDmpId().equals(dmp) && dmpUser.getUserId().equals(user) && dmpUser.getRole() == role) {
return dmpUser;
};
}
return null;
}
public void finalize(UUID id, List<UUID> descriptionIds) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(id)), Permission.FinalizeDmp);
DmpEntity dmp = this.queryFactory.query(DmpQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(id).isActive(IsActive.Active).first();
@ -828,7 +895,8 @@ public class DmpServiceImpl implements DmpService {
throw new MyApplicationException("DMP is already finalized");
}
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).dmpIds(id).isActive(IsActive.Active).collect();
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
.authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).dmpIds(id).isActive(IsActive.Active).collect();
for (DescriptionEntity description: descriptions) {
if (descriptionIds.contains(description.getId())){
@ -836,7 +904,7 @@ public class DmpServiceImpl implements DmpService {
if (description.getStatus().equals(DescriptionStatus.Finalized)){
throw new MyApplicationException("Description is already finalized");
}
if (this.descriptionService.validate(List.of(description.getId())).get(0).getResult().equals(DescriptionValidationOutput.Invalid)){
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
throw new MyApplicationException("Description is invalid");
}
description.setStatus(DescriptionStatus.Finalized);
@ -850,38 +918,40 @@ public class DmpServiceImpl implements DmpService {
}
}
DmpStatus previousStatus = dmp.getStatus();
dmp.setStatus(DmpStatus.Finalized);
dmp.setUpdatedAt(Instant.now());
dmp.setFinalizedAt(Instant.now());
this.entityManager.merge(dmp);
this.entityManager.flush();
this.updateVersionStatusAndSave(dmp, previousStatus, dmp.getStatus());
this.entityManager.flush();
this.elasticService.persistDmp(dmp);
this.sendNotification(dmp);
}
public void undoFinalize(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
public void undoFinalize(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(id)), Permission.UndoFinalizeDmp);
DmpEntity dmp = this.queryFactory.query(DmpQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(id).isActive(IsActive.Active).firstAs(fields);
if (dmp == null){
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
}
if (dmp == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (dmp.getStatus().equals(DmpStatus.Draft)){
throw new MyApplicationException("DMP is already drafted");
}
if (!dmp.getStatus().equals(DmpStatus.Finalized)) throw new MyApplicationException("DMP is already drafted");
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).types(EntityType.DMP).entityIds(dmp.getId());
if (entityDoiQuery != null && entityDoiQuery.count() > 0){
throw new MyApplicationException("DMP is deposited");
}
if (entityDoiQuery.count() > 0) throw new MyApplicationException("DMP is deposited");
dmp.setStatus(DmpStatus.Draft);
dmp.setUpdatedAt(Instant.now());
this.entityManager.merge(dmp);
this.entityManager.flush();
this.updateVersionStatusAndSave(dmp, DmpStatus.Finalized, dmp.getStatus());
this.entityManager.flush();
this.sendNotification(dmp);
}
@ -986,7 +1056,7 @@ public class DmpServiceImpl implements DmpService {
}
public void dmpInvitationAccept(String token) throws InvalidApplicationException, IOException {
public void dmpInvitationAccept(String token) {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.DmpInvitation).isActive(IsActive.Active).first();
if (action == null){