argos/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java

1095 lines
57 KiB
Java

package eu.eudat.service.dmp;
import com.fasterxml.jackson.core.JsonProcessingException;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.authorization.Permission;
import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.XmlHandlingService;
import eu.eudat.commons.enums.*;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.scope.user.UserScope;
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.dmpblueprint.ReferenceTypeFieldEntity;
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;
import eu.eudat.configurations.notification.NotificationProperties;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.*;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.event.DmpTouchedEvent;
import eu.eudat.event.EventBroker;
import eu.eudat.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import eu.eudat.integrationevent.outbox.dmptouched.DmpTouchedIntegrationEventHandler;
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
import eu.eudat.model.*;
import eu.eudat.model.builder.DmpBuilder;
import eu.eudat.model.builder.DmpUserBuilder;
import eu.eudat.model.deleter.*;
import eu.eudat.model.file.FileEnvelope;
import eu.eudat.model.persist.*;
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.*;
import eu.eudat.service.actionconfirmation.ActionConfirmationService;
import eu.eudat.service.description.DescriptionService;
import eu.eudat.service.elastic.ElasticService;
import eu.eudat.service.transformer.FileTransformerService;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
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;
import org.jetbrains.annotations.NotNull;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.io.IOException;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class DmpServiceImpl implements DmpService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpServiceImpl.class));
private final EntityManager entityManager;
private final AuthorizationService authorizationService;
private final DeleterFactory deleterFactory;
private final BuilderFactory builderFactory;
private final QueryFactory queryFactory;
private final ConventionService conventionService;
private final ErrorThesaurusProperties errors;
private final MessageSource messageSource;
private final XmlHandlingService xmlHandlingService;
private final JsonHandlingService jsonHandlingService;
private final UserScope userScope;
private final EventBroker eventBroker;
private final DescriptionService descriptionService;
private final FileTransformerService fileTransformerService;
private final NotifyIntegrationEventHandler eventHandler;
private final NotificationProperties notificationProperties;
private final ActionConfirmationService actionConfirmationService;
private final gr.cite.tools.validation.ValidatorFactory validatorFactory;
private final ElasticService elasticService;
private final DmpTouchedIntegrationEventHandler dmpTouchedIntegrationEventHandler;
private final AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler;
private final AuthorizationContentResolver authorizationContentResolver;
@Autowired
public DmpServiceImpl(
EntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
QueryFactory queryFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource,
XmlHandlingService xmlHandlingService,
JsonHandlingService jsonHandlingService,
UserScope userScope,
EventBroker eventBroker,
DescriptionService descriptionService,
NotifyIntegrationEventHandler eventHandler,
NotificationProperties notificationProperties,
ActionConfirmationService actionConfirmationService,
FileTransformerService fileTransformerService,
ValidatorFactory validatorFactory,
ElasticService elasticService,
DmpTouchedIntegrationEventHandler dmpTouchedIntegrationEventHandler,
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.builderFactory = builderFactory;
this.queryFactory = queryFactory;
this.conventionService = conventionService;
this.errors = errors;
this.messageSource = messageSource;
this.xmlHandlingService = xmlHandlingService;
this.jsonHandlingService = jsonHandlingService;
this.userScope = userScope;
this.eventBroker = eventBroker;
this.descriptionService = descriptionService;
this.fileTransformerService = fileTransformerService;
this.eventHandler = eventHandler;
this.notificationProperties = notificationProperties;
this.actionConfirmationService = actionConfirmationService;
this.validatorFactory = validatorFactory;
this.elasticService = elasticService;
this.dmpTouchedIntegrationEventHandler = dmpTouchedIntegrationEventHandler;
this.annotationEntityTouchedIntegrationEventHandler = annotationEntityTouchedIntegrationEventHandler;
this.authorizationContentResolver = authorizationContentResolver;
}
public Dmp persist(DmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
if (isUpdate) this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(model.getId())), Permission.EditDmp);
else this.authorizationService.authorizeForce(Permission.NewDmp);
DmpEntity data = this.patchAndSave(model);
DmpBlueprintEntity blueprintEntity = this.entityManager.find(DmpBlueprintEntity.class, data.getBlueprintId());
if (blueprintEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{data.getBlueprintId(), DmpBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale()));
eu.eudat.commons.types.dmpblueprint.DefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(eu.eudat.commons.types.dmpblueprint.DefinitionEntity.class, blueprintEntity.getDefinition());
if (definition == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{data.getBlueprintId(), eu.eudat.commons.types.dmpblueprint.DefinitionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.patchAndSaveReferences(this.buildDmpReferencePersists(model.getProperties()), data.getId(), definition);
this.patchAndSaveTemplates(data.getId(), model.getDescriptionTemplates());
if (!isUpdate && userScope.isSet()) {
this.addOwner(data);
if (model.getUsers() == null) model.setUsers(new ArrayList<>());
if (model.getUsers().stream().noneMatch(x-> x.getUser() != null && x.getUser().equals(this.userScope.getUserIdSafe()) && DmpUserRole.Owner.equals(x.getRole()))) model.getUsers().add(this.createOwnerPersist());
}
this.eventBroker.emit(new DmpTouchedEvent(data.getId()));
this.dmpTouchedIntegrationEventHandler.handle(DmpTouchedIntegrationEventHandler.buildEventFromPersistModel(model));
this.annotationEntityTouchedIntegrationEventHandler.handle(AnnotationEntityTouchedIntegrationEventHandler.buildEventFromPersistModel(model));
this.sendNotification(data);
this.assignUsers(data.getId(), this.inviteUserOrAssignUsers(data.getId(), model.getUsers(), false), null, false);
this.elasticService.persistDmp(data);
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
}
private DmpUserPersist createOwnerPersist() {
DmpUserPersist persist = new DmpUserPersist();
persist.setRole(DmpUserRole.Owner);
persist.setUser(userScope.getUserIdSafe());
return persist;
}
private void addOwner(DmpEntity dmpEntity) throws InvalidApplicationException {
DmpUserEntity data = new DmpUserEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
data.setUpdatedAt(Instant.now());
data.setRole(DmpUserRole.Owner);
data.setUserId(userScope.getUserId());
data.setDmpId(dmpEntity.getId());
this.entityManager.persist(data);
}
private void sendNotification(DmpEntity dmp) throws InvalidApplicationException {
List<DmpUserEntity> existingUsers = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(dmp.getId())
.isActives(IsActive.Active)
.collect();
if (existingUsers == null || existingUsers.size() <= 1){
return;
}
for (DmpUserEntity dmpUser : existingUsers) {
if (!dmpUser.getUserId().equals(this.userScope.getUserIdSafe())){
UserEntity user = this.queryFactory.query(UserQuery.class).ids(dmpUser.getUserId()).first();
if (user != null){
this.createDmpNotificationEvent(dmp, user, NotificationContactType.EMAIL);
this.createDmpNotificationEvent(dmp, user, NotificationContactType.IN_APP);
}
}
}
}
private void createDmpNotificationEvent(DmpEntity dmp, UserEntity user, NotificationContactType type) throws InvalidApplicationException {
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
event.setUserId(this.userScope.getUserId());
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue()));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(type);
this.applyNotificationType(dmp.getStatus(), event);
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first().getName()));
fieldInfoList.add(new FieldInfo("{name}", DataType.String, dmp.getLabel()));
fieldInfoList.add(new FieldInfo("{id}", DataType.String, dmp.getId().toString()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
}
private void applyNotificationType(DmpStatus status, NotifyIntegrationEvent event) {
switch (status) {
case Draft:
event.setNotificationType(notificationProperties.getDmpModifiedType());
break;
case Finalized:
event.setNotificationType(notificationProperties.getDmpFinalisedType());
break;
default:
throw new MyApplicationException("Unsupported Dmp Status.");
}
}
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException {
logger.debug("deleting dmp: {}", id);
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, 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());
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());
newDmp.setIsActive(IsActive.Active);
newDmp.setCreatedAt(Instant.now());
newDmp.setUpdatedAt(Instant.now());
newDmp.setGroupId(oldDmpEntity.getGroupId());
newDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
newDmp.setVersion((short)(oldDmpEntity.getVersion() + 1));
newDmp.setDescription(model.getDescription());
newDmp.setLabel(model.getLabel());
newDmp.setLanguage(oldDmpEntity.getLanguage());
newDmp.setStatus(DmpStatus.Draft);
newDmp.setProperties(oldDmpEntity.getProperties());
newDmp.setBlueprintId(model.getBlueprintId());
newDmp.setCreatorId(this.userScope.getUserId());
this.entityManager.persist(newDmp);
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(model.getId())
.isActives(IsActive.Active)
.collect();
List<DmpReferenceEntity> dmpReferences = this.queryFactory.query(DmpReferenceQuery.class)
.dmpIds(model.getId())
.isActives(IsActive.Active)
.collect();
List<DmpDescriptionTemplateEntity> dmpDescriptionTemplates = this.queryFactory.query(DmpDescriptionTemplateQuery.class)
.dmpIds(model.getId())
.isActive(IsActive.Active)
.collect();
for (DmpUserEntity dmpUser : dmpUsers) {
DmpUserEntity newUser = new DmpUserEntity();
newUser.setId(UUID.randomUUID());
newUser.setDmpId(newDmp.getId());
newUser.setUserId(dmpUser.getUserId());
newUser.setRole(dmpUser.getRole());
newUser.setCreatedAt(Instant.now());
newUser.setUpdatedAt(Instant.now());
newUser.setIsActive(IsActive.Active);
this.entityManager.persist(newUser);
}
for (DmpReferenceEntity dmpReference : dmpReferences) {
DmpReferenceEntity newReference = new DmpReferenceEntity();
newReference.setId(UUID.randomUUID());
newReference.setDmpId(newDmp.getId());
newReference.setReferenceId(dmpReference.getReferenceId());
newReference.setData(dmpReference.getData());
newReference.setCreatedAt(Instant.now());
newReference.setUpdatedAt(Instant.now());
newReference.setIsActive(IsActive.Active);
this.entityManager.persist(newReference);
}
for (DmpDescriptionTemplateEntity dmpDescriptionTemplate : dmpDescriptionTemplates) {
DmpDescriptionTemplateEntity newTemplate = new DmpDescriptionTemplateEntity();
newTemplate.setId(UUID.randomUUID());
newTemplate.setDmpId(newDmp.getId());
newTemplate.setDescriptionTemplateGroupId(dmpDescriptionTemplate.getDescriptionTemplateGroupId());
newTemplate.setSectionId(dmpDescriptionTemplate.getSectionId());
newTemplate.setCreatedAt(Instant.now());
newTemplate.setUpdatedAt(Instant.now());
newTemplate.setIsActive(IsActive.Active);
this.entityManager.persist(newTemplate);
}
for (UUID descriptionId : model.getDescriptions()) {
this.descriptionService.clone(newDmp.getId(), descriptionId);
}
this.entityManager.flush();
this.updateVersionStatusAndSave(newDmp, DmpStatus.Draft, newDmp.getStatus());
this.entityManager.flush();
this.elasticService.persistDmp(oldDmpEntity);
this.elasticService.persistDmp(newDmp);
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);
DmpEntity existingDmpEntity = this.queryFactory.query(DmpQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(model.getId()).firstAs(fields);
if (!this.conventionService.isValidGuid(model.getId()) || existingDmpEntity == null)
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
DmpEntity newDmp = new DmpEntity();
newDmp.setId(UUID.randomUUID());
newDmp.setIsActive(IsActive.Active);
newDmp.setCreatedAt(Instant.now());
newDmp.setUpdatedAt(Instant.now());
newDmp.setGroupId(UUID.randomUUID());
newDmp.setVersion((short) 1);
newDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
newDmp.setDescription(model.getDescription());
newDmp.setLabel(model.getLabel());
newDmp.setLanguage(existingDmpEntity.getLanguage());
newDmp.setStatus(DmpStatus.Draft);
newDmp.setProperties(existingDmpEntity.getProperties());
newDmp.setBlueprintId(existingDmpEntity.getBlueprintId());
newDmp.setAccessType(existingDmpEntity.getAccessType());
newDmp.setCreatorId(this.userScope.getUserId());
this.entityManager.persist(newDmp);
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(model.getId())
.isActives(IsActive.Active)
.collect();
List<DmpReferenceEntity> dmpReferences = this.queryFactory.query(DmpReferenceQuery.class)
.dmpIds(model.getId())
.isActives(IsActive.Active)
.collect();
List<DmpDescriptionTemplateEntity> dmpDescriptionTemplates = this.queryFactory.query(DmpDescriptionTemplateQuery.class)
.dmpIds(model.getId())
.isActive(IsActive.Active)
.collect();
for (DmpUserEntity dmpUser : dmpUsers) {
DmpUserEntity newUser = new DmpUserEntity();
newUser.setId(UUID.randomUUID());
newUser.setDmpId(newDmp.getId());
newUser.setUserId(dmpUser.getUserId());
newUser.setRole(dmpUser.getRole());
newUser.setCreatedAt(Instant.now());
newUser.setUpdatedAt(Instant.now());
newUser.setIsActive(IsActive.Active);
this.entityManager.persist(newUser);
}
for (DmpReferenceEntity dmpReference : dmpReferences) {
DmpReferenceEntity newReference = new DmpReferenceEntity();
newReference.setId(UUID.randomUUID());
newReference.setDmpId(newDmp.getId());
newReference.setReferenceId(dmpReference.getReferenceId());
newReference.setData(dmpReference.getData());
newReference.setCreatedAt(Instant.now());
newReference.setUpdatedAt(Instant.now());
newReference.setIsActive(IsActive.Active);
this.entityManager.persist(newReference);
}
for (DmpDescriptionTemplateEntity dmpDescriptionTemplate : dmpDescriptionTemplates) {
DmpDescriptionTemplateEntity newTemplate = new DmpDescriptionTemplateEntity();
newTemplate.setId(UUID.randomUUID());
newTemplate.setDmpId(newDmp.getId());
newTemplate.setDescriptionTemplateGroupId(dmpDescriptionTemplate.getDescriptionTemplateGroupId());
newTemplate.setSectionId(dmpDescriptionTemplate.getSectionId());
newTemplate.setCreatedAt(Instant.now());
newTemplate.setUpdatedAt(Instant.now());
newTemplate.setIsActive(IsActive.Active);
this.entityManager.persist(newTemplate);
}
this.entityManager.flush();
this.elasticService.persistDmp(newDmp);
DmpEntity resultingDmpEntity = this.queryFactory.query(DmpQuery.class).ids(newDmp.getId()).firstAs(fields);
return this.builderFactory.builder(DmpBuilder.class).build(fields, resultingDmpEntity);
}
@Override
public List<DmpUser> assignUsers(UUID dmpId, List<DmpUserPersist> model, FieldSet fieldSet, boolean disableDelete) throws InvalidApplicationException, IOException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(dmpId)), Permission.AssignDmpUsers);
if (!disableDelete && (model == null || model.stream().noneMatch(x-> x.getUser() != null && DmpUserRole.Owner.equals(x.getRole())))) throw new MyApplicationException("At least one owner required");
DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, dmpId);
if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{dmpId, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
List<DmpUserEntity> existingUsers = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(dmpId)
.isActives(IsActive.Active)
.collect();
List<UUID> updatedCreatedIds = new ArrayList<>();
for (DmpUserPersist dmpUser : model) {
DmpUserEntity dmpUserEntity = existingUsers.stream().filter(x-> x.getDmpId().equals(dmpId) && x.getUserId().equals(dmpUser.getUser()) && x.getRole().equals(dmpUser.getRole()) && Objects.equals(dmpUser.getSectionId(), x.getSectionId())).findFirst().orElse(null);
if (dmpUserEntity == null){
dmpUserEntity = new DmpUserEntity();
dmpUserEntity.setId(UUID.randomUUID());
dmpUserEntity.setDmpId(dmpId);
dmpUserEntity.setUserId(dmpUser.getUser());
dmpUserEntity.setRole(dmpUser.getRole());
dmpUserEntity.setSectionId(dmpUser.getSectionId());
dmpUserEntity.setCreatedAt(Instant.now());
dmpUserEntity.setUpdatedAt(Instant.now());
dmpUserEntity.setIsActive(IsActive.Active);
this.entityManager.persist(dmpUserEntity);
}
updatedCreatedIds.add(dmpUserEntity.getId());
}
List<DmpUserEntity> toDelete = existingUsers.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
if (!toDelete.isEmpty() && !disableDelete) this.deleterFactory.deleter(DmpUserDeleter.class).delete(toDelete);
this.entityManager.flush();
List<DmpUserEntity> persisted = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(dmpId)
.isActives(IsActive.Active)
.collect();
this.elasticService.persistDmp(dmpEntity);
return this.builderFactory.builder(DmpUserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fieldSet, DmpUser._id, DmpUser._hash), persisted);
}
@Override
public Dmp removeUser(DmpUserRemovePersist model, FieldSet fields) throws InvalidApplicationException, IOException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(model.getDmpId())), Permission.AssignDmpUsers);
DmpEntity data = this.entityManager.find(DmpEntity.class, model.getDmpId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
List<DmpUserEntity> existingUsers = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(model.getDmpId()).ids(model.getId()).userRoles(model.getRole())
.collect();
if (!existingUsers.isEmpty()) this.deleterFactory.deleter(DmpUserDeleter.class).delete(existingUsers);
this.entityManager.flush();
DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, model.getDmpId());
if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDmpId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.elasticService.persistDmp(dmpEntity);
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
}
@Override
public ResponseEntity<byte[]> export(UUID id, String transformerId, String exportType) throws InvalidApplicationException, IOException {
HttpHeaders headers = new HttpHeaders();
FileEnvelope fileEnvelope = this.fileTransformerService.exportDmp(id, transformerId, exportType);
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
private DmpEntity patchAndSave(DmpPersist model) throws JsonProcessingException, InvalidApplicationException {
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
DmpEntity data;
if (isUpdate) {
data = this.entityManager.find(DmpEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (model.getStatus() != null && model.getStatus() == DmpStatus.Finalized && data.getStatus() != DmpStatus.Finalized) {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(model.getId())), Permission.FinalizeDmp);
data.setStatus(model.getStatus());
data.setFinalizedAt(Instant.now());
}
} else {
data = new DmpEntity();
data.setId(UUID.randomUUID());
data.setGroupId(UUID.randomUUID());
data.setVersion((short) 1);
data.setStatus(DmpStatus.Draft);
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());
data.setProperties(this.jsonHandlingService.toJson(this.buildDmpPropertiesEntity(model.getProperties())));
data.setDescription(model.getDescription());
data.setAccessType(model.getAccessType());
data.setUpdatedAt(Instant.now());
if (isUpdate)
this.entityManager.merge(data);
else {
this.entityManager.persist(data);
}
this.entityManager.flush();
this.updateVersionStatusAndSave(data, previousStatus, data.getStatus());
this.entityManager.flush();
return data;
}
private @NotNull DmpPropertiesEntity buildDmpPropertiesEntity(DmpPropertiesPersist persist){
DmpPropertiesEntity data = new DmpPropertiesEntity();
if (persist == null) return data;
if (!this.conventionService.isListNullOrEmpty(persist.getContacts())){
data.setContacts(new ArrayList<>());
for (DmpContactPersist contactPersist: persist.getContacts()) {
data.getContacts().add(this.buildDmpContactEntity(contactPersist));
}
}
if (persist.getDmpBlueprintValues() != null && !persist.getDmpBlueprintValues().isEmpty()){
data.setDmpBlueprintValues(new ArrayList<>());
for (DmpBlueprintValuePersist fieldValuePersist: persist.getDmpBlueprintValues().values()) {
if (!this.conventionService.isNullOrEmpty(fieldValuePersist.getFieldValue())) data.getDmpBlueprintValues().add(this.buildDmpBlueprintValueEntity(fieldValuePersist));
}
}
return data;
}
private @NotNull DmpContactEntity buildDmpContactEntity(DmpContactPersist persist){
DmpContactEntity data = new DmpContactEntity();
if (persist == null) return data;
data.setEmail(persist.getEmail());
data.setLastName(persist.getLastName());
data.setFirstName(persist.getFirstName());
data.setUserId(persist.getUserId());
return data;
}
private @NotNull DmpBlueprintValueEntity buildDmpBlueprintValueEntity(DmpBlueprintValuePersist persist){
DmpBlueprintValueEntity data = new DmpBlueprintValueEntity();
if (persist == null) return data;
data.setValue(persist.getFieldValue());
data.setFieldId(persist.getFieldId());
return data;
}
private @NotNull List<DmpReferencePersist> buildDmpReferencePersists(DmpPropertiesPersist persist){
List<DmpReferencePersist> dmpReferencePersists = new ArrayList<>();
if (persist.getDmpBlueprintValues() != null && !persist.getDmpBlueprintValues().isEmpty()){
for (DmpBlueprintValuePersist fieldValuePersist: persist.getDmpBlueprintValues().values()) {
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);
dmpReferencePersists.add(dmpReferencePersist);
}
}
}
}
return dmpReferencePersists;
}
private void patchAndSaveReferences(List<DmpReferencePersist> models, UUID dmpId, eu.eudat.commons.types.dmpblueprint.DefinitionEntity blueprintDefinition) throws InvalidApplicationException {
if (models == null) models = new ArrayList<>();
List<DmpReferenceEntity> dmpReferences = this.queryFactory.query(DmpReferenceQuery.class).dmpIds(dmpId).collect();
Map<UUID, List<DmpReferenceEntity>> dmpReferenceEntityByReferenceId = new HashMap<>();
for (DmpReferenceEntity dmpReferenceEntity : dmpReferences){
List<DmpReferenceEntity> dmpReferenceEntities = dmpReferenceEntityByReferenceId.getOrDefault(dmpReferenceEntity.getReferenceId(), null);
if (dmpReferenceEntities == null) {
dmpReferenceEntities = new ArrayList<>();
dmpReferenceEntityByReferenceId.put(dmpReferenceEntity.getReferenceId(), dmpReferenceEntities);
}
dmpReferenceEntities.add(dmpReferenceEntity);
}
Map<UUID, DmpReferenceDataEntity> dmpReferenceDataEntityMap = new HashMap<>();
for (DmpReferenceEntity dmpReferenceEntity : dmpReferences){
dmpReferenceDataEntityMap.put(dmpReferenceEntity.getId(), this.jsonHandlingService.fromJsonSafe(DmpReferenceDataEntity.class, dmpReferenceEntity.getData()));
}
List<UUID> updatedCreatedIds = new ArrayList<>();
for (DmpReferencePersist model : models) {
ReferencePersist referencePersist = model.getReference();
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()));
} else {
ReferenceTypeFieldEntity fieldEntity = blueprintDefinition.getFieldById(model.getData().getBlueprintFieldId()).stream().filter(x-> x.getCategory().equals(DmpBlueprintFieldCategory.ReferenceType)).map(x-> (ReferenceTypeFieldEntity)x).findFirst().orElse(null);
if (fieldEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getData().getBlueprintFieldId(), ReferenceTypeFieldEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
referenceEntity = this.queryFactory.query(ReferenceQuery.class).sourceTypes(referencePersist.getSourceType()).typeIds(fieldEntity.getReferenceTypeId()).sources(referencePersist.getSource()).isActive(IsActive.Active).references(referencePersist.getReference()).first();
if (referenceEntity == null){
referenceEntity = new ReferenceEntity();
referenceEntity.setId(UUID.randomUUID());
referenceEntity.setLabel(referencePersist.getLabel());
referenceEntity.setIsActive(IsActive.Active);
referenceEntity.setCreatedAt(Instant.now());
referenceEntity.setTypeId(fieldEntity.getReferenceTypeId());
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);
}
}
DmpReferenceEntity data = null;
List<DmpReferenceEntity> 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.setId(UUID.randomUUID());
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());
if (isUpdate) this.entityManager.merge(data);
else this.entityManager.persist(data);
}
List<DmpReferenceEntity> 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();
}
private void patchAndSaveTemplates(UUID id, List<DmpDescriptionTemplatePersist> models) throws InvalidApplicationException {
if (models == null) models = new ArrayList<>();
List<DmpDescriptionTemplateEntity> items = this.queryFactory.query(DmpDescriptionTemplateQuery.class).isActive(IsActive.Active).dmpIds(id).collect();
List<UUID> updatedCreatedIds = new ArrayList<>();
for (DmpDescriptionTemplatePersist model : models) {
DmpDescriptionTemplateEntity data = items.stream().filter(x -> x.getDescriptionTemplateGroupId().equals(model.getDescriptionTemplateGroupId()) && x.getSectionId().equals(model.getSectionId())).findFirst().orElse(null);
if (data == null){
data = new DmpDescriptionTemplateEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
data.setUpdatedAt(Instant.now());
data.setDmpId(id);
data.setSectionId(model.getSectionId());
data.setDescriptionTemplateGroupId(model.getDescriptionTemplateGroupId());
this.entityManager.persist(data);
}
updatedCreatedIds.add(data.getId());
}
List<DmpDescriptionTemplateEntity> toDelete = items.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
this.deleterFactory.deleter(DmpDescriptionTemplateDeleter.class).delete(toDelete);
}
private @NotNull DefinitionEntity buildDefinitionEntity(DefinitionPersist persist){
DefinitionEntity data = new DefinitionEntity();
if (persist == null) return data;
if (!this.conventionService.isListNullOrEmpty(persist.getFields())){
data.setFields(new ArrayList<>());
for (FieldPersist fieldPersist: persist.getFields()) {
data.getFields().add(this.buildDmpContactEntity(fieldPersist));
}
}
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;
data.setCode(persist.getCode());
data.setDataType(persist.getDataType());
data.setCode(persist.getCode());
return data;
}
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();
if (dmp == null){
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
}
if (dmp.getStatus().equals(DmpStatus.Finalized)){
throw new MyApplicationException("DMP is already finalized");
}
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())){
// description to be finalized
if (description.getStatus().equals(DescriptionStatus.Finalized)){
throw new MyApplicationException("Description is already finalized");
}
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
throw new MyApplicationException("Description is invalid");
}
description.setStatus(DescriptionStatus.Finalized);
description.setUpdatedAt(Instant.now());
description.setFinalizedAt(Instant.now());
this.entityManager.merge(description);
} else if (description.getStatus().equals(DescriptionStatus.Draft)) {
// description to be canceled
description.setStatus(DescriptionStatus.Canceled);
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), true);
}
}
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 {
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.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.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);
}
// invites
public void inviteUserOrAssignUsers(UUID id, List<DmpUserPersist> users) throws InvalidApplicationException, JAXBException, IOException {
this.inviteUserOrAssignUsers(id, users, true);
}
private List<DmpUserPersist> inviteUserOrAssignUsers(UUID id, List<DmpUserPersist> users, boolean persistUsers) throws InvalidApplicationException, JAXBException, IOException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(id)), Permission.InviteDmpUsers);
DmpEntity dmp = this.queryFactory.query(DmpQuery.class).ids(id).first();
if (dmp == null){
throw new InvalidApplicationException("Dmp does not exist!");
}
List<DmpUserPersist> usersToAssign = new ArrayList<>();
for (DmpUserPersist user :users) {
UUID userId = null;
if (user.getUser() != null){
userId = user.getUser();
} else if (user.getEmail() != null) {
UserContactInfoEntity contactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(user.getEmail()).types(ContactInfoType.Email).first();
if (contactInfoEntity != null){
userId = contactInfoEntity.getUserId();
}
}
if (userId != null){
user.setUser(userId);
usersToAssign.add(user);
if (this.userScope.getUserId() != userId){
this.sendDmpInvitationExistingUser(user.getUser(), dmp, user.getRole());
}
}else if (user.getEmail() != null) {
this.sendDmpInvitationExternalUser(user.getEmail(),dmp, user.getRole());
}
}
if(!usersToAssign.isEmpty() && persistUsers) this.assignUsers(id, usersToAssign, null, true);
return usersToAssign;
}
private void sendDmpInvitationExistingUser(UUID userId, DmpEntity dmp, DmpUserRole role) throws InvalidApplicationException {
UserEntity recipient = this.queryFactory.query(UserQuery.class).ids(userId).isActive(IsActive.Active).first();
String email = this.queryFactory.query(UserContactInfoQuery.class).userIds(recipient.getId()).first().getValue();
this.createDmpInvitationExistingUserEvent(recipient, dmp, role, email, NotificationContactType.EMAIL);
this.createDmpInvitationExistingUserEvent(recipient, dmp, role, email, NotificationContactType.IN_APP);
}
private void createDmpInvitationExistingUserEvent(UserEntity recipient, DmpEntity dmp, DmpUserRole role, String email, NotificationContactType type) throws InvalidApplicationException {
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
event.setUserId(this.userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(type);
event.setNotificationType(notificationProperties.getDmpInvitationExistingUserType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, recipient.getName()));
fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserIdSafe()).first().getName()));
fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel()));
fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, role.toString()));
fieldInfoList.add(new FieldInfo("{id}", DataType.String, dmp.getId().toString()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
}
private void sendDmpInvitationExternalUser(String email, DmpEntity dmp, DmpUserRole role) throws JAXBException, InvalidApplicationException {
String token = this.createActionConfirmation(email, dmp, role);
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
event.setUserId(this.userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getDmpInvitationExternalUserType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, email));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel()));
fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, role.toString()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
}
private String createActionConfirmation(String email, DmpEntity dmp, DmpUserRole role) throws JAXBException, InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(ActionConfirmationType.DmpInvitation);
persist.setStatus(ActionConfirmationStatus.Requested);
persist.setToken(UUID.randomUUID().toString());
persist.setDmpInvitation(new DmpInvitationPersist(email, dmp.getId(), role));
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
this.actionConfirmationService.persist(persist, null);
return persist.getToken();
}
public void dmpInvitationAccept(String token) {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.DmpInvitation).isActive(IsActive.Active).first();
if (action == null){
throw new MyApplicationException("Token does not exist!");
}
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){
throw new MyApplicationException("Invitation is already confirmed!");
}
if (action.getExpiresAt().compareTo(Instant.now()) < 0){
throw new MyApplicationException("Token has expired!");
}
DmpInvitationEntity dmpInvitation = this.xmlHandlingService.fromXmlSafe(DmpInvitationEntity.class, action.getData());
DmpUserEntity data = new DmpUserEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
data.setUpdatedAt(Instant.now());
data.setRole(dmpInvitation.getRole());
data.setUserId(this.userScope.getUserIdSafe());
data.setDmpId(dmpInvitation.getDmpId());
this.entityManager.persist(data);
action.setStatus(ActionConfirmationStatus.Accepted);
this.entityManager.merge(action);
}
}