diff --git a/dmp-backend/Dockerfile.CI b/dmp-backend/Dockerfile.CI index 866a3a692..5747c9969 100644 --- a/dmp-backend/Dockerfile.CI +++ b/dmp-backend/Dockerfile.CI @@ -12,4 +12,4 @@ RUN mvn package FROM adoptopenjdk/openjdk11:alpine-jre WORKDIR /app COPY --from=MAVEN_BUILD /build/web/target/web-1.0-SNAPSHOT.jar /app/app.jar -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dspring.profiles.active=${PROF}", "-Dspring.config.additional-location=/files/config/", "-jar","/app/app.jar"] +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dspring.profiles.active=${PROF}", "-Dspring.config.additional-location=/files/config/", "-cp", "/app/app.jar", "-Dloader.path=/files/repo-jars", "org.springframework.boot.loader.PropertiesLauncher"] diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java index ca33c0830..ac8ce47d7 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java @@ -87,7 +87,7 @@ public class DMPDaoImpl extends DatabaseAccess implements DMPDao { } if (criteria.hasDoi()) { - query.where((builder, root) -> builder.not(builder.isNull(root.get("doi")))); + query.where((builder, root) -> builder.not(builder.isNull(root.join("dois").get("id")))); } query.where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue())); return query; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java index 5df4bdf88..d996ea95e 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java @@ -80,7 +80,7 @@ public class DatasetDaoImpl extends DatabaseAccess implements DatasetDa query.where((builder, root) -> root.get("profile").get("id").in(criteria.getDatasetTemplates())); if (criteria.hasDoi()) { - query.where((builder, root) -> builder.not(builder.isNull(root.get("dmp").get("doi")))); + query.where((builder, root) -> builder.not(builder.isNull(root.join("dmp").join("dois").get("id")))); } query.where((builder, root) -> builder.notEqual(root.get("status"), Dataset.Status.DELETED.getValue())); query.where((builder, root) -> builder.notEqual(root.get("status"), Dataset.Status.CANCELED.getValue())); diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java new file mode 100644 index 000000000..ebc6aad1a --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java @@ -0,0 +1,10 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccessLayer; +import eu.eudat.data.entities.EntityDoi; + +import java.util.UUID; + +public interface EntityDoiDao extends DatabaseAccessLayer { + EntityDoi findFromDoi(String doi); +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java new file mode 100644 index 000000000..4eaf59b87 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java @@ -0,0 +1,56 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccess; +import eu.eudat.data.dao.databaselayer.service.DatabaseService; +import eu.eudat.data.entities.EntityDoi; +import eu.eudat.queryable.QueryableList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@Component("EntityDoiDao") +public class EntityDoiDaoImpl extends DatabaseAccess implements EntityDoiDao { + + @Autowired + public EntityDoiDaoImpl(DatabaseService databaseService){ + super(databaseService); + } + + + @Override + public EntityDoi createOrUpdate(EntityDoi item) { + return this.getDatabaseService().createOrUpdate(item, EntityDoi.class); + } + + @Override + public CompletableFuture createOrUpdateAsync(EntityDoi item) { + return CompletableFuture.supplyAsync(() -> this.createOrUpdate(item)); + } + + @Override + public EntityDoi find(UUID id) { + return this.getDatabaseService().getQueryable(EntityDoi.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle(); + } + + @Override + public EntityDoi findFromDoi(String doi) { + return this.getDatabaseService().getQueryable(EntityDoi.class).where((builder, root) -> builder.equal(root.get("doi"), doi)).getSingle(); + } + + @Override + public EntityDoi find(UUID id, String hint) { + return null; + } + + @Override + public void delete(EntityDoi item) { + this.getDatabaseService().delete(item); + } + + @Override + public QueryableList asQueryable() { + return this.getDatabaseService().getQueryable(EntityDoi.class); + } +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDao.java index 868a58e71..c334b63d4 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDao.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDao.java @@ -3,7 +3,9 @@ package eu.eudat.data.dao.entities; import eu.eudat.data.dao.DatabaseAccessLayer; import eu.eudat.data.entities.FileUpload; +import java.util.List; import java.util.UUID; public interface FileUploadDao extends DatabaseAccessLayer { + List getFileUploads(UUID entityId); } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDaoImpl.java index d50780bc5..47cc10066 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/FileUploadDaoImpl.java @@ -7,6 +7,7 @@ import eu.eudat.queryable.QueryableList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -33,6 +34,11 @@ public class FileUploadDaoImpl extends DatabaseAccess implements Fil return getDatabaseService().getQueryable(FileUpload.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle(); } + @Override + public List getFileUploads(UUID entityId) { + return this.getDatabaseService().getQueryable(FileUpload.class).where((builder, root) -> builder.equal(root.get("entityId"), entityId)).toList(); + } + @Override public FileUpload find(UUID id, String hint) { return null; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java index b4f212210..cbd796ca2 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java @@ -181,8 +181,8 @@ public class DMP implements DataEntity { @Convert(converter = DateToUTCConverter.class) private Date publishedAt; - @Column(name = "\"DOI\"") - private String doi; + @OneToMany(mappedBy = "entityId", fetch = FetchType.LAZY) + private Set dois; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "\"Project\"") @@ -339,12 +339,12 @@ public class DMP implements DataEntity { this.publishedAt = publishedAt; } - public String getDoi() { - return doi; - } - public void setDoi(String doi) { - this.doi = doi; - } + public Set getDois() { + return dois; + } + public void setDois(Set dois) { + this.dois = dois; + } public Project getProject() { return project; @@ -380,7 +380,7 @@ public class DMP implements DataEntity { if (entity.getStatus().equals(DMPStatus.FINALISED.getValue())) this.setFinalizedAt(new Date()); if (entity.isPublic) this.setPublishedAt(new Date()); if (entity.getUsers() != null) this.users = entity.getUsers(); - if (entity.getDoi() != null && entity.getDoi().trim().isEmpty()) this.doi = entity.doi; + this.dois = entity.getDois(); this.extraProperties = entity.getExtraProperties(); } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java new file mode 100644 index 000000000..a0b86c6c5 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java @@ -0,0 +1,121 @@ +package eu.eudat.data.entities; + +import eu.eudat.data.converters.DateToUTCConverter; +import eu.eudat.data.entities.helpers.EntityBinder; +import eu.eudat.queryable.queryableentity.DataEntity; +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@Entity +@Table(name = "\"EntityDoi\"") +public class EntityDoi implements DataEntity { + public enum EntityType { + DMP + } + + @Id + @Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)") + private UUID id; + + @Enumerated(EnumType.STRING) + @Type(type = "eu.eudat.configurations.typedefinition.PostgreSQLEnumType") + @Column(name = "\"EntityType\"", nullable = false) + private EntityType entityType; + + @Column(name = "\"RepositoryId\"", nullable = false) + private String repositoryId; + + @Column(name = "\"Doi\"", nullable = false) + private String doi; + + @Column(name = "\"CreatedAt\"", nullable = false) + @Convert(converter = DateToUTCConverter.class) + private Date createdAt; + + @Column(name = "\"UpdatedAt\"", nullable = false) + @Convert(converter = DateToUTCConverter.class) + private Date updatedAt; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "\"EntityId\"", nullable = false) + private DMP entityId; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public EntityType getEntityType() { + return entityType; + } + public void setEntityType(EntityType entityType) { + this.entityType = entityType; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDoi() { + return doi; + } + public void setDoi(String doi) { + this.doi = doi; + } + + public Date getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public DMP getEntityId() { + return entityId; + } + public void setEntityId(DMP entityId) { + this.entityId = entityId; + } + + @Override + public void update(EntityDoi doi) { + this.entityType = doi.getEntityType(); + this.repositoryId = doi.getRepositoryId(); + this.doi = doi.getDoi(); + this.createdAt = doi.getCreatedAt(); + this.updatedAt = doi.getUpdatedAt(); + this.entityId = doi.getEntityId(); + } + + @Override + public UUID getKeys() { + return this.id; + } + + @Override + public EntityDoi buildFromTuple(List tuple, List fields, String base) { + String currentBase = base.isEmpty() ? "" : base + "."; + if (fields.contains(currentBase + "id")) this.id = EntityBinder.fromTuple(tuple, currentBase + "id"); + if (fields.contains(currentBase + "entityId")) + this.entityId = tuple.stream().map(x -> new DMP().buildFromTuple(Arrays.asList(x), fields , base.isEmpty() ? "entityId" : base + "." + "entityId")).collect(Collectors.toList()).get(0); + return this; + } +} diff --git a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dmp.java b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dmp.java index a7ca04c6a..8d5129521 100644 --- a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dmp.java +++ b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dmp.java @@ -57,7 +57,7 @@ public class Dmp implements ElasticEntity { private Date modified; private Date finalizedAt; private Date publishedAt; - private String doi; + private List dois; public UUID getId() { return id; @@ -203,12 +203,12 @@ public class Dmp implements ElasticEntity { this.publishedAt = publishedAt; } - public String getDoi() { - return doi; + public List getDois() { + return dois; } - public void setDoi(String doi) { - this.doi = doi; + public void setDois(List dois) { + this.dois = dois; } @Override @@ -280,7 +280,17 @@ public class Dmp implements ElasticEntity { builder.field(MapKey.MODIFIED.getName(), this.modified); builder.field(MapKey.FINALIZEDAT.getName(), this.finalizedAt); builder.field(MapKey.PUBLISHEDAT.getName(), this.publishedAt); - builder.field(MapKey.DOI.getName(), this.doi); + if (this.dois != null && !this.dois.isEmpty()) { + builder.startArray(MapKey.DOIS.getName()); + this.dois.forEach(doi -> { + try { + doi.toElasticEntity(builder); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + }); + builder.endArray(); + } builder.endObject(); return builder; } @@ -329,8 +339,8 @@ public class Dmp implements ElasticEntity { if (fields.get(MapKey.PUBLISHEDAT.getName()) != null) { this.publishedAt = Date.from(Instant.parse(fields.get(MapKey.PUBLISHEDAT.getName()).toString())); } - if (fields.get(MapKey.DOI.getName()) != null) { - this.doi = fields.get(MapKey.DOI.getName()).toString(); + if (fields.get(MapKey.DOIS.getName()) != null) { + this.dois = ((List>) fields.get(MapKey.DOIS.getName())).stream().map(map -> new Doi().fromElasticEntity(map)).collect(Collectors.toList()); } } return this; @@ -355,7 +365,7 @@ public class Dmp implements ElasticEntity { MODIFIED ("modified"), FINALIZEDAT ("finalizedAt"), PUBLISHEDAT ("publishedAt"), - DOI ("doi"); + DOIS ("dois"); private final String name; diff --git a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Doi.java b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Doi.java new file mode 100644 index 000000000..0b990a437 --- /dev/null +++ b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Doi.java @@ -0,0 +1,65 @@ +package eu.eudat.elastic.entities; + +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Map; +import java.util.UUID; + +public class Doi implements ElasticEntity{ + private UUID id; + private String repositoryId; + private String doi; + private UUID dmp; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDoi() { + return doi; + } + public void setDoi(String doi) { + this.doi = doi; + } + + public UUID getDmp() { + return dmp; + } + public void setDmp(UUID dmp) { + this.dmp = dmp; + } + + @Override + public XContentBuilder toElasticEntity(XContentBuilder builder) throws IOException { + builder.startObject(); + builder.field("id", this.id.toString()); + builder.field("repositoryId", this.repositoryId); + builder.field("doi", this.doi); + builder.field("dmp", this.dmp.toString()); + builder.endObject(); + return builder; + } + + @Override + public Doi fromElasticEntity(Map fields) { + if (fields == null || fields.isEmpty()) { + return null; + } + this.id = UUID.fromString((String) fields.get("id")); + this.repositoryId = (String) fields.get("repositoryId"); + this.doi = (String) fields.get("doi"); + this.dmp = UUID.fromString((String) fields.get("dmp")); + return this; + } +} diff --git a/dmp-backend/web/pom.xml b/dmp-backend/web/pom.xml index 6d05bdeb8..7567d150e 100644 --- a/dmp-backend/web/pom.xml +++ b/dmp-backend/web/pom.xml @@ -26,13 +26,16 @@ queryable 1.0-SNAPSHOT - eu.eudat elastic 1.0.0-SNAPSHOT - + + gr.cite.opendmp + repositorydepositbase + 1.0.0 + @@ -220,6 +223,39 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + true + eu.eudat.EuDatApplication + dependency-jars/ + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.5.1 + + + copy-dependencies + package + + copy-dependencies + + + + ${project.build.directory}/dependency-jars/ + + + + + diff --git a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java index 31e87ddf5..5ed228762 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java +++ b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java @@ -8,7 +8,7 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.scheduling.annotation.EnableAsync; -@SpringBootApplication +@SpringBootApplication(scanBasePackages = {"eu.eudat", "eu.eudat.depositinterface"}) @EnableAsync public class EuDatApplication extends SpringBootServletInitializer { private static final Logger logger = LoggerFactory.getLogger(EuDatApplication.class); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java new file mode 100644 index 000000000..fdc266bfc --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java @@ -0,0 +1,67 @@ +package eu.eudat.controllers; + +import eu.eudat.logic.managers.DepositManager; +import eu.eudat.logic.security.claims.ClaimedAuthorities; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.models.data.doi.DepositCode; +import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; +import eu.eudat.models.data.doi.RepositoryConfig; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.security.Principal; +import eu.eudat.types.ApiMessageCode; +import eu.eudat.types.Authorities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@CrossOrigin +@RequestMapping(value = {"/api/deposit/"}) +public class DepositController extends BaseController { + private static final Logger logger = LoggerFactory.getLogger(DepositController.class); + + private DepositManager depositManager; + + @Autowired + public DepositController(ApiContext apiContext, DepositManager depositManager){ + super(apiContext); + this.depositManager = depositManager; + } + + @RequestMapping(method = RequestMethod.GET, value = {"/repos"}) + public @ResponseBody + ResponseEntity>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + List ids = this.depositManager.getAvailableRepos(); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(ids)); + } + + @RequestMapping(method = RequestMethod.POST, value = {"/getAccessToken"}) + public @ResponseBody + ResponseEntity> getAccessToken(@RequestBody DepositCode depositCode, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { + String accessToken = this.depositManager.authenticate(depositCode.getRepositoryId(), depositCode.getCode()); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(accessToken)); + } + + @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"}) + public @ResponseBody + ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + try { + Doi doi = this.depositManager.deposit(depositRequest, principal); + if(doi != null){ + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); + } + else{ + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan")); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); + } + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index f492e2a9d..25ab0217a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -15,6 +15,8 @@ import eu.eudat.data.enumeration.notification.NotifyState; import eu.eudat.data.query.items.table.dataset.DatasetTableRequest; import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem; import eu.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; import eu.eudat.elastic.criteria.DmpCriteria; import eu.eudat.elastic.entities.Collaborator; import eu.eudat.elastic.entities.Dmp; @@ -29,6 +31,7 @@ import eu.eudat.logic.builders.entity.UserInfoBuilder; import eu.eudat.logic.mapper.elastic.DmpMapper; import eu.eudat.logic.mapper.elastic.criteria.DmpCriteriaMapper; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; +import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.forms.VisibilityRuleService; import eu.eudat.logic.services.forms.VisibilityRuleServiceImpl; @@ -45,6 +48,8 @@ import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized; import eu.eudat.models.data.dmp.*; +import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field; @@ -57,11 +62,10 @@ import eu.eudat.models.data.project.ProjectDMPEditorModel; import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.models.data.userinfo.UserListingModel; -import eu.eudat.models.deposit.zenodo.ZenodoDeposit; -import eu.eudat.models.deposit.zenodo.mapper.DMPToZenodoMapper; import eu.eudat.queryable.QueryableList; import eu.eudat.types.Authorities; import eu.eudat.types.MetricNames; +import org.apache.commons.io.IOUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; @@ -70,11 +74,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; -import org.springframework.core.io.FileSystemResource; import org.springframework.http.*; import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import org.w3c.dom.Document; @@ -86,6 +87,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import java.io.*; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -93,6 +95,8 @@ import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; @Component public class DataManagementPlanManager { @@ -114,9 +118,11 @@ public class DataManagementPlanManager { private UserManager userManager; private final MetricsManager metricsManager; private final ConfigLoader configLoader; + private List repositoriesDeposit; @Autowired - public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager, MetricsManager metricsManager, ConfigLoader configLoader) { + public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager, + MetricsManager metricsManager, ConfigLoader configLoader, List repositoriesDeposit) { this.apiContext = apiContext; this.datasetManager = datasetManager; this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); @@ -126,6 +132,7 @@ public class DataManagementPlanManager { this.metricsManager = metricsManager; this.configLoader = configLoader; this.objectMapper = new ObjectMapper(); + this.repositoriesDeposit = repositoriesDeposit; } /* @@ -749,7 +756,7 @@ public class DataManagementPlanManager { metricsManager.decreaseValue(MetricNames.DMP, 1, MetricNames.DRAFT); break; case 1: - if (oldDmp.getDoi() != null) { + if (oldDmp.getDois() != null && !oldDmp.getDois().isEmpty()) { metricsManager.decreaseValue(MetricNames.DMP, 1, MetricNames.DOIED); } if (oldDmp.isPublic()) { @@ -1057,9 +1064,9 @@ public class DataManagementPlanManager { }); UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); sendNotification(dmp, user, NotificationType.DMP_PUBLISH); - if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) { - this.createZenodoDoi(dmp.getId(), principal, true); - } +// if (dmp.getDois() != null && !dmp.getDois().isEmpty()) { +// this.createZenodoDoi(dmp.getId(), principal, true); +// } } @Transactional @@ -1151,6 +1158,10 @@ public class DataManagementPlanManager { throw new Exception("User does not have the privilege to do this action."); if (dmp.getStatus().equals(DMP.DMPStatus.ACTIVE.getValue())) throw new Exception("DMP is already Active"); + if (dmp.isPublic()) + throw new Exception("DMP is publicly available"); + if (!dmp.getDois().isEmpty()) + throw new Exception("DMP is deposited"); dmp.setStatus(DMP.DMPStatus.ACTIVE.getValue()); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); UUID dmpId = dmp.getId(); @@ -2006,23 +2017,28 @@ public class DataManagementPlanManager { * DOI Generation * */ - private String getPreviousDOI(UUID groupId, UUID selfId) { + private String getPreviousDOI(UUID groupId, UUID selfId, String repositoryId) { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); List groupIds = new ArrayList<>(); groupIds.add(groupId); criteria.setGroupIds(groupIds); criteria.setAllVersions(true); List dmps = this.databaseRepository.getDmpDao().getWithCriteria(criteria).toList(); - String doi = null; + dmps.sort((DMP d1, DMP d2) -> d2.getVersion() - d1.getVersion()); for (DMP dmp: dmps) { if (!dmp.getId().equals(selfId)) { - if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) { - doi = dmp.getDoi(); + if (dmp.getDois() != null && !dmp.getDois().isEmpty()) { + for (Iterator it = dmp.getDois().iterator(); it.hasNext(); ) { + EntityDoi entityDoi = it.next(); + if(entityDoi.getRepositoryId().equals(repositoryId)){ + return entityDoi.getDoi(); + } + } } } } - return doi; + return null; } private String getUnpublishedDOI(String DOI, String token, Integer version) { @@ -2064,6 +2080,22 @@ public class DataManagementPlanManager { /*if (dmp.getDoi() != null) throw new Exception("DMP already has a DOI");*/ + FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); + String name = file.getFilename().substring(0, file.getFilename().length() - 5); + File pdfFile = PDFUtils.convertToPDF(file, environment); + String fileName = name + ".pdf"; + ResponseEntity jsonFile; + try { + jsonFile = getRDAJsonDocument(id.toString(), principal); + } catch (Exception e) { + throw e; + } + String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId(), "Zenodo"); + + File supportingFilesZip = this.createSupportingFilesZip(dmp); + + DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfFile, fileName, jsonFile, supportingFilesZip, previousDOI); + String zenodoToken = ""; try { if (this.userManager.isDOITokenValid(principal)) { @@ -2072,136 +2104,126 @@ public class DataManagementPlanManager { } catch (NonValidTokenException e) { zenodoToken = this.environment.getProperty("zenodo.access_token"); } - // First step, post call to Zenodo, to create the entry. - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - headers.setContentType(MediaType.APPLICATION_JSON); - ZenodoDeposit deposit = DMPToZenodoMapper.fromDMP(dmp, environment, configLoader); - //if (Objects.requireNonNull(environment.getProperty("spring.profiles.active")).contains("devel")) { - String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(deposit); - logger.info(json); - //} - HttpEntity request = new HttpEntity<>(deposit, headers); - Map createResponse; - LinkedHashMap links; - String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId()); - String unpublishedUrl = null; - String publishUrl; - String finalDoi; - try { - if (previousDOI == null) { - String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + zenodoToken; - createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody(); - links = (LinkedHashMap) createResponse.get("links"); - finalDoi = (String) createResponse.get("conceptdoi"); - } else { - unpublishedUrl = this.getUnpublishedDOI(previousDOI, zenodoToken, dmp.getVersion()); - if (unpublishedUrl == null) { - //It requires more than one step to create a new version - //First, get the deposit related to the concept DOI - String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; - ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); - createResponse = listResponses.getBody()[0]; - links = (LinkedHashMap) createResponse.get("links"); - //Second, make the new version (not in the links?) - String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken; - createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); - links = (LinkedHashMap) createResponse.get("links"); - //Third, get the new deposit - String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; - createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); - links = (LinkedHashMap) createResponse.get("links"); - finalDoi = (String) createResponse.get("conceptdoi"); - //At this point it might fail to perform the next requests so enclose them with try catch - try { - //Forth, update the new deposit's metadata - String updateUrl = links.get("self") + "?access_token=" + zenodoToken; - restTemplate.put(updateUrl, request); - //And finally remove pre-existing files from it - String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken; - ResponseEntity fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class); - for (Map file : fileListResponse.getBody()) { - String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken; - restTemplate.delete(fileDeleteUrl); - } - } catch (Exception e) { - //In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed) - restTemplate.delete(latestDraftUrl); - throw e; - } - } - else { - String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; - ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); - createResponse = listResponses.getBody()[0]; - links = (LinkedHashMap) createResponse.get("links"); + String finalDoi = null; + for(RepositoryDeposit repo: this.repositoriesDeposit) { //temp + if(repo.getConfiguration().getRepositoryId().equals("Zenodo")) { + finalDoi = repo.deposit(dmpDepositModel, zenodoToken); + if (finalDoi != null) { + EntityDoi doiEntity = new EntityDoi(); + doiEntity.setId(UUID.randomUUID()); + doiEntity.setEntityType(EntityDoi.EntityType.DMP); + doiEntity.setDoi(finalDoi); + doiEntity.setRepositoryId("Zenodo"); + Date now = new Date(); + doiEntity.setCreatedAt(now); + doiEntity.setUpdatedAt(now); + doiEntity.setEntityId(dmp); + apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity); + + dmp.getDois().add(doiEntity); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); } } - - if (!update) { - if (unpublishedUrl == null) { - // Second step, add the file to the entry. - FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); - String name = file.getFilename().substring(0, file.getFilename().length() - 5); - File pdfFile = PDFUtils.convertToPDF(file, environment); - String fileName = name + ".pdf"; - FileSystemResource fileSystemResource = new FileSystemResource(pdfFile); - HttpEntity addFileMapRequest = new HttpEntity<>(fileSystemResource, null); - - String addFileUrl = links.get("bucket") + "/" + fileName + "?access_token=" + zenodoToken; - restTemplate.put(addFileUrl, addFileMapRequest); - Files.deleteIfExists(file.getFile().toPath()); - - ResponseEntity jsonFile; - try { - jsonFile = getRDAJsonDocument(id.toString(), principal); - } catch (Exception e) { - throw e; - } - UUID jsonFileUUID = UUID.randomUUID(); - File tempJsonFile = new File(this.environment.getProperty("temp.temp") + jsonFileUUID.toString() + ".json"); - try (FileOutputStream jsonFos = new FileOutputStream(tempJsonFile)) { - jsonFos.write(jsonFile.getBody()); - jsonFos.flush(); - } - fileSystemResource = new FileSystemResource(tempJsonFile); - HttpHeaders jsonHeaders = new HttpHeaders(); - jsonHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE); - addFileMapRequest = new HttpEntity<>(fileSystemResource, jsonHeaders); - String jsonFileName = jsonFile.getHeaders().get("Content-Disposition").get(0).substring(jsonFile.getHeaders().get("Content-Disposition").get(0).lastIndexOf('=') + 1); - addFileUrl = links.get("bucket") + "/" + jsonFileName + "?access_token=" + zenodoToken; - restTemplate.put(addFileUrl, addFileMapRequest); - Files.deleteIfExists(tempJsonFile.toPath()); - - - // Third post call to Zenodo to publish the entry and return the DOI. - publishUrl = links.get("publish") + "?access_token=" + zenodoToken; - } else { - publishUrl = unpublishedUrl + "?access_token=" + zenodoToken; - } -// if (dmp.isPublic()) { - Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); - finalDoi = (String) publishResponce.get("conceptdoi"); -// } - } else { - Map editResponce = restTemplate.postForObject(links.get("edit") + "?access_token=" + zenodoToken, "", Map.class); - restTemplate.put(links.get("self") + "?access_token=" + zenodoToken, request); - Map publishResponce = restTemplate.postForObject(links.get("publish") + "?access_token=" + zenodoToken, "", Map.class); - finalDoi = (String) publishResponce.get("conceptdoi"); - } - - if (finalDoi != null) { - dmp.setDoi(finalDoi); - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); - } - return finalDoi; - } catch (HttpClientErrorException | HttpServerErrorException ex) { - //ObjectMapper ob = new ObjectMapper(); - Map parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), HashMap.class); - throw new IOException(parsedException.get("message"), ex); } + if(supportingFilesZip != null) { + Files.deleteIfExists(supportingFilesZip.toPath()); + } + Files.deleteIfExists(pdfFile.toPath()); + Files.deleteIfExists(file.getFile().toPath()); + + return finalDoi; + } + + public Doi createDoi(DepositRequest depositRequest, Principal principal) throws Exception { + DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId())); + if (!isUserOwnerOfDmp(dmp, principal)) + throw new Exception("User is not authorized to invoke this action"); + if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) + throw new Exception("DMP is not finalized"); + /*if (dmp.getDoi() != null) + throw new Exception("DMP already has a DOI");*/ + + FileEnvelope file = getWordDocument(depositRequest.getDmpId(), principal, configLoader); + String name = file.getFilename().substring(0, file.getFilename().length() - 5).replaceAll("[^a-zA-Z0-9_+ ]", "").replace(" ", "_").replace(",", "_"); + File pdfFile = PDFUtils.convertToPDF(file, environment); + String fileName = name + ".pdf"; + ResponseEntity jsonFile; + try { + jsonFile = getRDAJsonDocument(depositRequest.getDmpId(), principal); + } catch (Exception e) { + throw e; + } + String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId(), depositRequest.getRepositoryId()); + + File supportingFilesZip = this.createSupportingFilesZip(dmp); + + DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfFile, fileName, jsonFile, supportingFilesZip, previousDOI); + + Optional repo = this.repositoriesDeposit.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(depositRequest.getRepositoryId())).findFirst(); + String finalDoi = repo.map(r -> { + try { + return r.deposit(dmpDepositModel, depositRequest.getAccessToken()); + } catch (Exception e) { + logger.error(e.getMessage(), e); + return null; + } + }).orElse(null); + Doi doiModel = null; + if (finalDoi != null) { + + EntityDoi doiEntity = new EntityDoi(); + doiEntity.setId(UUID.randomUUID()); + doiEntity.setEntityType(EntityDoi.EntityType.DMP); + doiEntity.setDoi(finalDoi); + doiEntity.setRepositoryId(depositRequest.getRepositoryId()); + Date now = new Date(); + doiEntity.setCreatedAt(now); + doiEntity.setUpdatedAt(now); + doiEntity.setEntityId(dmp); + apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity); + + dmp.getDois().add(doiEntity); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + + doiModel = new Doi().fromDataModel(doiEntity); + + } + if(supportingFilesZip != null) { + Files.deleteIfExists(supportingFilesZip.toPath()); + } + Files.deleteIfExists(pdfFile.toPath()); + Files.deleteIfExists(file.getFile().toPath()); + + return doiModel; + } + + private File createSupportingFilesZip(DMP dmp) throws IOException { + FileOutputStream fout = new FileOutputStream(this.environment.getProperty("temp.temp") + "supportingFiles.zip"); + ZipOutputStream zout = new ZipOutputStream(fout); + + boolean hasFileUploaded = false; + Set datasets = dmp.getDataset(); + for (Dataset dataset : datasets) { + List files = this.apiContext.getOperationsContext().getDatabaseRepository().getFileUploadDao().getFileUploads(dataset.getId()); + for (FileUpload f : files) { + if(!f.getIsDeleted()){ + File exportFile = new File(this.environment.getProperty("file.storage") + f.getId()); + String filename = f.getName().replace(" ", "_").replace(",", "_"); + byte[] content = Files.readAllBytes(exportFile.toPath()); + ZipEntry ze = new ZipEntry(filename); + zout.putNextEntry(ze); + zout.write(content, 0, content.length); + zout.closeEntry(); + hasFileUploaded = true; + } + } + } + zout.close(); + if(!hasFileUploaded){ + Files.deleteIfExists(new File(this.environment.getProperty("temp.temp") + "supportingFiles.zip").toPath()); + } + return hasFileUploaded ? new File(this.environment.getProperty("temp.temp") + "supportingFiles.zip") : null; } /* diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java new file mode 100644 index 000000000..982b7d399 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java @@ -0,0 +1,60 @@ +package eu.eudat.logic.managers; + +import eu.eudat.data.entities.DMP; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import eu.eudat.exceptions.security.NonValidTokenException; +import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper; +import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; +import eu.eudat.logic.utilities.documents.pdf.PDFUtils; +import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; +import eu.eudat.models.data.doi.RepositoryConfig; +import eu.eudat.models.data.security.Principal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Component +public class DepositManager { + private static final Logger logger = LoggerFactory.getLogger(DepositManager.class); + + private List repositories; + private DataManagementPlanManager dataManagementPlanManager; + + @Autowired + public DepositManager(List repositories, DataManagementPlanManager dataManagementPlanManager){ + this.repositories = repositories; + this.dataManagementPlanManager = dataManagementPlanManager; + } + + public List getAvailableRepos() { + List reposConfigModel = new ArrayList<>(); + for (RepositoryDeposit r: this.repositories) { + RepositoryConfig repoModel = new RepositoryConfig(); + RepositoryDepositConfiguration repoConf = r.getConfiguration(); + if(repoConf != null) { + reposConfigModel.add(repoModel.toModel(repoConf)); + } + } + return reposConfigModel; + } + + public String authenticate(String id, String code) { + Optional repo = repositories.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(id)).findFirst(); + return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null); + } + + public Doi deposit(DepositRequest depositRequest, Principal principal) throws Exception { + return this.dataManagementPlanManager.createDoi(depositRequest, principal); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java deleted file mode 100644 index 68803e021..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java +++ /dev/null @@ -1,27 +0,0 @@ -package eu.eudat.logic.proxy.config; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class DOIFunder { - - @JsonProperty("Funder") - private String funder; - @JsonProperty("DOI") - private String DOI; - - public String getFunder() { - return funder; - } - - public void setFunder(String funder) { - this.funder = funder; - } - - public String getDOI() { - return DOI; - } - - public void setDOI(String DOI) { - this.DOI = DOI; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java index 08dc4062c..175442eda 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java @@ -1,6 +1,5 @@ package eu.eudat.logic.proxy.config.configloaders; -import eu.eudat.logic.proxy.config.DOIFunder; import eu.eudat.logic.proxy.config.ExternalUrls; import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -15,5 +14,4 @@ public interface ConfigLoader { XWPFDocument getDatasetDocument(); ConfigurableProviders getConfigurableProviders(); Map getKeyToSourceMap(); - List getDOIFunders(); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java index a1d65877c..36c6d3ac3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java @@ -2,7 +2,6 @@ package eu.eudat.logic.proxy.config.configloaders; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import eu.eudat.logic.proxy.config.DOIFunder; import eu.eudat.logic.proxy.config.ExternalUrls; import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -41,7 +40,6 @@ public class DefaultConfigLoader implements ConfigLoader { private XWPFDocument datasetDocument; private ConfigurableProviders configurableProviders; private Map keyToSourceMap; - private List doiFunders = new ArrayList<>(); @Autowired private Environment environment; @@ -207,18 +205,6 @@ public class DefaultConfigLoader implements ConfigLoader { return keyToSourceMap; } - @Override - public List getDOIFunders() { - if (doiFunders == null || doiFunders.isEmpty()) { - try { - List> tempdoiFunders = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.doi_funder")), List.class); - doiFunders = tempdoiFunders.stream().map(map -> mapper.convertValue(map, DOIFunder.class) ).collect(Collectors.toList()); - } catch (IOException e) { - logger.error(e.getLocalizedMessage(), e); - } - } - return doiFunders; - } private Document getXmlDocumentFromFilePath(String filePath) { InputStream is = null; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java new file mode 100644 index 000000000..2997f534c --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java @@ -0,0 +1,74 @@ +package eu.eudat.logic.security.repositorydeposit.mapper; + +import eu.eudat.data.entities.*; +import eu.eudat.depositinterface.models.*; +import org.springframework.http.ResponseEntity; + +import java.io.File; +import java.util.stream.Collectors; + +public class DMPToDepositMapper { + + public static DMPDepositModel fromDMP(DMP entity, File pdfFile, String fileName, ResponseEntity jsonFile, File supportingFilesZip, String previousDOI) { + DMPDepositModel deposit = new DMPDepositModel(); + deposit.setId(entity.getId()); + deposit.setVersion(entity.getVersion()); + deposit.setLabel(entity.getLabel()); + deposit.setDescription(entity.getDescription()); + deposit.setPublic(entity.isPublic()); + deposit.setUsers(entity.getUsers().stream().map(DMPToDepositMapper::fromUserDMP).collect(Collectors.toSet())); + deposit.setOrganisations(entity.getOrganisations().stream().map(DMPToDepositMapper::fromOrganisation).collect(Collectors.toSet())); + deposit.setResearchers(entity.getResearchers().stream().map(DMPToDepositMapper::fromResearcher).collect(Collectors.toSet())); + deposit.setGrant(fromGrant(entity.getGrant())); + + deposit.setPdfFile(pdfFile); + deposit.setPdfFileName(fileName); + deposit.setRdaJson(jsonFile); + deposit.setSupportingFilesZip(supportingFilesZip); + deposit.setPreviousDOI(previousDOI); + + deposit.setExtraProperties(entity.getExtraProperties()); + return deposit; + } + + private static UserDMPDepositModel fromUserDMP(UserDMP entity){ + UserDMPDepositModel deposit = new UserDMPDepositModel(); + deposit.setUser(fromUserInfo(entity.getUser())); + deposit.setRole(entity.getRole()); + return deposit; + } + + private static UserInfoDepositModel fromUserInfo(UserInfo entity){ + UserInfoDepositModel deposit = new UserInfoDepositModel(); + deposit.setName(entity.getName()); + deposit.setEmail(entity.getEmail()); + return deposit; + } + + private static OrganisationDepositModel fromOrganisation(Organisation entity){ + OrganisationDepositModel deposit = new OrganisationDepositModel(); + deposit.setLabel(entity.getLabel()); + return deposit; + } + + private static ResearcherDepositModel fromResearcher(Researcher entity){ + ResearcherDepositModel deposit = new ResearcherDepositModel(); + deposit.setLabel(entity.getLabel()); + deposit.setReference(entity.getReference()); + return deposit; + } + + private static GrantDepositModel fromGrant(Grant entity){ + GrantDepositModel deposit = new GrantDepositModel(); + deposit.setId(entity.getId()); + deposit.setReference(entity.getReference()); + deposit.setFunder(fromFunder(entity.getFunder())); + return deposit; + } + + private static FunderDepositModel fromFunder(Funder entity){ + FunderDepositModel deposit = new FunderDepositModel(); + deposit.setLabel(entity.getLabel()); + return deposit; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index 67225a76d..99e088a1c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -60,5 +60,7 @@ public interface DatabaseRepository { FileUploadDao getFileUploadDao(); + EntityDoiDao getEntityDoiDao(); + void detachEntity(T entity); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index 7228b5b2f..2e2dd4c63 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -39,6 +39,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { private LockDao lockDao; private NotificationDao notificationDao; private FileUploadDao fileUploadDao; + private EntityDoiDao entityDoiDao; private EntityManager entityManager; @@ -317,6 +318,15 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { this.fileUploadDao = fileUploadDao; } + @Override + public EntityDoiDao getEntityDoiDao() { + return entityDoiDao; + } + + @Autowired + public void setEntityDoiDao(EntityDoiDao entityDoiDao) { + this.entityDoiDao = entityDoiDao; + } public void detachEntity(T entity) { this.entityManager.detach(entity); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java index 3023a888c..a325194b9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java @@ -1036,9 +1036,8 @@ public class WordBuilder { r.setText(text, 0); } if(text.contains("{ARGOS.DMP.DOI}")){ - String doi = dmpEntity.getDoi(); - if(doi != null) - text = text.replace("{ARGOS.DMP.DOI}", doi); + if(dmpEntity.getDois() != null && !dmpEntity.getDois().isEmpty()) + text = text.replace("{ARGOS.DMP.DOI}", dmpEntity.getDois().iterator().next().getDoi()); else text = text.replace("{ARGOS.DMP.DOI}", "-"); r.setText(text, 0); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java index cc2dcd4fb..6c4018f81 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java @@ -4,6 +4,7 @@ import eu.eudat.data.entities.*; import eu.eudat.logic.utilities.builders.XmlBuilder; import eu.eudat.models.DataModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.funder.Funder; @@ -40,7 +41,7 @@ public class DataManagementPlan implements DataModel { private List dynamicFields; private Map properties; private List users; - private String doi; + private List dois; private Project project; private Funder funder; private Boolean isPublic; @@ -194,11 +195,11 @@ public class DataManagementPlan implements DataModel { this.users = users; } - public String getDoi() { - return doi; + public List getDois() { + return dois; } - public void setDoi(String doi) { - this.doi = doi; + public void setDois(List dois) { + this.dois = dois; } public Project getProject() { @@ -280,7 +281,7 @@ public class DataManagementPlan implements DataModel { this.status = entity.getStatus(); this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>(); this.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>(); - this.doi = entity.getDoi(); + this.dois = entity.getDois() != null ? entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()): new ArrayList<>(); if (entity.getProject() != null) { this.project = new Project(); @@ -376,7 +377,7 @@ public class DataManagementPlan implements DataModel { this.status = entity.getStatus(); this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>(); this.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>(); - this.doi = entity.getDoi(); + this.dois = entity.getDois() != null ? entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()): new ArrayList<>(); this.grant.fromDataModel(entity.getGrant()); if (entity.getProject() != null) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java new file mode 100644 index 000000000..a567dc9da --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java @@ -0,0 +1,21 @@ +package eu.eudat.models.data.doi; + +public class DepositCode { + + private String repositoryId; + private String code; + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java new file mode 100644 index 000000000..b6ee1f4a3 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java @@ -0,0 +1,29 @@ +package eu.eudat.models.data.doi; + +public class DepositRequest { + + private String repositoryId; + private String dmpId; + private String accessToken; + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDmpId() { + return dmpId; + } + public void setDmpId(String dmpId) { + this.dmpId = dmpId; + } + + public String getAccessToken() { + return accessToken; + } + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java new file mode 100644 index 000000000..9a877dc4d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java @@ -0,0 +1,85 @@ +package eu.eudat.models.data.doi; + +import eu.eudat.data.entities.EntityDoi; +import eu.eudat.models.DataModel; +import eu.eudat.models.data.dmp.DataManagementPlan; + +import java.util.Date; +import java.util.UUID; + +public class Doi implements DataModel { + private UUID id; + private String repositoryId; + private String doi; + private Date createdAt; + private Date updatedAt; + private DataManagementPlan dmp; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDoi() { + return doi; + } + public void setDoi(String doi) { + this.doi = doi; + } + + public Date getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public DataManagementPlan getDmp() { + return dmp; + } + public void setDmp(DataManagementPlan dmp) { + this.dmp = dmp; + } + + @Override + public Doi fromDataModel(EntityDoi entity) { + this.id = entity.getId(); + this.repositoryId = entity.getRepositoryId(); + this.doi = entity.getDoi(); + this.createdAt = entity.getCreatedAt(); + this.updatedAt = entity.getUpdatedAt(); + return this; + } + + @Override + public EntityDoi toDataModel() throws Exception { + EntityDoi entityDoi = new EntityDoi(); + entityDoi.setId(this.id); + entityDoi.setRepositoryId(this.repositoryId); + entityDoi.setDoi(this.doi); + entityDoi.setCreatedAt(this.createdAt); + entityDoi.setUpdatedAt(this.updatedAt); + return entityDoi; + } + + @Override + public String getHint() { + return null; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/RepositoryConfig.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/RepositoryConfig.java new file mode 100644 index 000000000..67eaab098 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/RepositoryConfig.java @@ -0,0 +1,65 @@ +package eu.eudat.models.data.doi; + +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; + +public class RepositoryConfig { + + private int depositType; + private String repositoryId; + private String repositoryAuthorizationUrl; + private String repositoryRecordUrl; + private String repositoryClientId; + private String redirectUri; + + public int getDepositType() { + return depositType; + } + public void setDepositType(int depositType) { + this.depositType = depositType; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getRepositoryAuthorizationUrl() { + return repositoryAuthorizationUrl; + } + public void setRepositoryAuthorizationUrl(String repositoryAuthorizationUrl) { + this.repositoryAuthorizationUrl = repositoryAuthorizationUrl; + } + + public String getRepositoryRecordUrl() { + return repositoryRecordUrl; + } + public void setRepositoryRecordUrl(String repositoryRecordUrl) { + this.repositoryRecordUrl = repositoryRecordUrl; + } + + public String getRepositoryClientId() { + return repositoryClientId; + } + public void setRepositoryClientId(String repositoryClientId) { + this.repositoryClientId = repositoryClientId; + } + + public String getRedirectUri() { + return redirectUri; + } + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public RepositoryConfig toModel(RepositoryDepositConfiguration r){ + this.setDepositType(r.getDepositType()); + this.setRepositoryId(r.getRepositoryId()); + this.setRepositoryAuthorizationUrl(r.getRepositoryAuthorizationUrl()); + this.setRepositoryRecordUrl(r.getRepositoryRecordUrl()); + this.setRepositoryClientId(r.getRepositoryClientId()); + this.setRedirectUri(r.getRedirectUri()); + return this; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java index e90d044c1..c207ab1fb 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java @@ -8,6 +8,7 @@ import eu.eudat.models.data.dataset.DatasetOverviewModel; import eu.eudat.models.data.dmp.AssociatedProfile; import eu.eudat.models.data.dmp.Organisation; import eu.eudat.models.data.dmp.Researcher; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.grant.GrantOverviewModel; import java.util.Date; @@ -35,7 +36,7 @@ public class DataManagementPlanOverviewModel implements DataModel dois; public String getId() { @@ -164,11 +165,11 @@ public class DataManagementPlanOverviewModel implements DataModel getDois() { + return dois; } - public void setDoi(String doi) { - this.doi = doi; + public void setDois(List dois) { + this.dois = dois; } @Override @@ -180,6 +181,9 @@ public class DataManagementPlanOverviewModel implements DataModel new Researcher().fromDataModel(item)).collect(Collectors.toList()); } + if(entity.getDois() != null){ + this.dois = entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()); + } return this; } @@ -208,7 +212,7 @@ public class DataManagementPlanOverviewModel implements DataModel new Doi().fromDataModel(item)).collect(Collectors.toList()); return this; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java index 47147fc4e..9d3cccf23 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java @@ -1,9 +1,6 @@ package eu.eudat.models.data.rda; -import eu.eudat.data.entities.DMP; -import eu.eudat.data.entities.Dataset; -import eu.eudat.data.entities.UserDMP; -import eu.eudat.data.entities.UserInfo; +import eu.eudat.data.entities.*; import eu.eudat.logic.managers.DatasetManager; import eu.eudat.models.data.security.Principal; @@ -146,8 +143,17 @@ public class DmpRDAExportModel { dmpRda.dataset.add(new DatasetRDAExportModel().fromDataModel(dataset, datasetManager, principal)); } dmpRda.description = entity.getDescription().replace("\n", " "); - if (entity.getDoi() != null) { - dmpRda.dmp_id = new IdRDAExportModel(entity.getDoi(), "zenodo"); + if (entity.getDois() != null && !entity.getDois().isEmpty()) { + boolean zenodoDoi = false; + for(EntityDoi doi: entity.getDois()){ + if(doi.getRepositoryId().equals("Zenodo")){ + dmpRda.dmp_id = new IdRDAExportModel(doi.getDoi(), "zenodo"); + zenodoDoi = true; + } + } + if(!zenodoDoi){ + dmpRda.dmp_id = new IdRDAExportModel(entity.getId().toString(), "other"); + } } else { dmpRda.dmp_id = new IdRDAExportModel(entity.getId().toString(), "other"); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java deleted file mode 100644 index b143338fc..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java +++ /dev/null @@ -1,18 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonValue; - -public enum ZenodoAccessRight { - RESTRICTED("restricted"), EMBARGOED("embargoed"), OPEN("open"); - - private final String value; - - ZenodoAccessRight(String value) { - this.value = value; - } - - @JsonValue - public String getValue() { - return value; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java deleted file mode 100644 index f644d3144..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java +++ /dev/null @@ -1,19 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoComunity { - - private String identifier; - - public String getIdentifier() { - return identifier; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java deleted file mode 100644 index 55ca86ed7..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java +++ /dev/null @@ -1,45 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoContributor { - private String name; - private String type; - private String affiliation; - private String orcid; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getAffiliation() { - return affiliation; - } - - public void setAffiliation(String affiliation) { - this.affiliation = affiliation; - } - - public String getOrcid() { - return orcid; - } - - public void setOrcid(String orcid) { - this.orcid = orcid; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java deleted file mode 100644 index c80a167c9..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java +++ /dev/null @@ -1,19 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoDeposit { - - private ZenodoDepositMetadata metadata; - - public ZenodoDepositMetadata getMetadata() { - return metadata; - } - - public void setMetadata(ZenodoDepositMetadata metadata) { - this.metadata = metadata; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java deleted file mode 100644 index 014239f69..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java +++ /dev/null @@ -1,159 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.time.Instant; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoDepositMetadata { - - private String title; - - @JsonProperty("upload_type") - private String uploadType; - - @JsonProperty("publication_type") - private String publicationType; - - private String description; - - private String version; - - private List communities; - - @JsonProperty("access_right") - private ZenodoAccessRight accessRight; - - @JsonProperty("access_conditions") - private String accessConditions; - - @JsonProperty("embargo_date") - private String embargoDate; - - private String license; - - @JsonProperty("related_identifiers") - private List relatedIdentifiers; - - private List contributors; - - private List grants; - - private List creators; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getUploadType() { - return uploadType; - } - - public void setUploadType(String uploadType) { - this.uploadType = uploadType; - } - - public String getPublicationType() { - return publicationType; - } - - public void setPublicationType(String publicationType) { - this.publicationType = publicationType; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public List getCommunities() { - return communities; - } - - public void setCommunities(List communities) { - this.communities = communities; - } - - public ZenodoAccessRight getAccessRight() { - return accessRight; - } - - public void setAccessRight(ZenodoAccessRight accessRight) { - this.accessRight = accessRight; - } - - public String getAccessConditions() { - return accessConditions; - } - - public void setAccessConditions(String accessConditions) { - this.accessConditions = accessConditions; - } - - public String getEmbargoDate() { - return embargoDate; - } - - public void setEmbargoDate(String embargoDate) { - this.embargoDate = embargoDate; - } - - public String getLicense() { - return license; - } - - public void setLicense(String license) { - this.license = license; - } - - public List getRelatedIdentifiers() { - return relatedIdentifiers; - } - - public void setRelatedIdentifiers(List relatedIdentifiers) { - this.relatedIdentifiers = relatedIdentifiers; - } - - public List getContributors() { - return contributors; - } - - public void setContributors(List contributors) { - this.contributors = contributors; - } - - public List getGrants() { - return grants; - } - - public void setGrants(List grants) { - this.grants = grants; - } - - public List getCreators() { - return creators; - } - - public void setCreators(List creators) { - this.creators = creators; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java deleted file mode 100644 index 292322a30..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java +++ /dev/null @@ -1,18 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoGrant { - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java deleted file mode 100644 index e5389602e..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoRelator { - - private String identifier; - private String relation; - - public String getIdentifier() { - return identifier; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } - - public String getRelation() { - return relation; - } - - public void setRelation(String relation) { - this.relation = relation; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java deleted file mode 100644 index f4a399f49..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java +++ /dev/null @@ -1,115 +0,0 @@ -package eu.eudat.models.deposit.zenodo.mapper; - -import eu.eudat.data.entities.DMP; -import eu.eudat.data.entities.Organisation; -import eu.eudat.data.entities.UserDMP; -import eu.eudat.logic.proxy.config.DOIFunder; -import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; -import eu.eudat.models.deposit.zenodo.*; -import org.springframework.core.env.Environment; - -import java.time.Instant; -import java.util.*; -import java.util.stream.Collectors; - -public class DMPToZenodoMapper { - - public static ZenodoDeposit fromDMP(DMP dmp, Environment environment, ConfigLoader configLoader) { - Map extraProperties = dmp.getExtraProperties() != null ? new org.json.JSONObject(dmp.getExtraProperties()).toMap() : new HashMap<>(); - ZenodoDeposit deposit = new ZenodoDeposit(); - deposit.setMetadata(new ZenodoDepositMetadata()); - deposit.getMetadata().setTitle(dmp.getLabel()); - deposit.getMetadata().setUploadType("publication"); - deposit.getMetadata().setPublicationType("datamanagementplan"); - deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

")); - deposit.getMetadata().setVersion(dmp.getVersion().toString()); - ZenodoComunity community = new ZenodoComunity(); - community.setIdentifier(environment.getProperty("zenodo.community")); - deposit.getMetadata().setCommunities(Collections.singletonList(community)); - if (extraProperties.get("visible") == null) { - deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED); - deposit.getMetadata().setAccessConditions(""); - } else { - if (((Boolean) extraProperties.get("visible"))) { - Instant publicationDate = Instant.parse(extraProperties.get("publicDate").toString()); - if (publicationDate.isBefore(Instant.now())) { - deposit.getMetadata().setAccessRight(ZenodoAccessRight.OPEN); - } else { - deposit.getMetadata().setAccessRight(ZenodoAccessRight.EMBARGOED); - deposit.getMetadata().setEmbargoDate(publicationDate.toString()); - } - - if (extraProperties.get("license") != null) { - deposit.getMetadata().setLicense(((Map) extraProperties.get("license")).get("pid").toString()); - } - } else { - deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED); - deposit.getMetadata().setAccessConditions(""); - } - } - if (dmp.isPublic()) { - ZenodoRelator relator = new ZenodoRelator(); - relator.setIdentifier((environment.getProperty("dmp.domain") + "/external/zenodo/" + dmp.getId().toString())); - relator.setRelation("isIdenticalTo"); - deposit.getMetadata().setRelatedIdentifiers(Collections.singletonList(relator)); - } - deposit.getMetadata().setContributors(new LinkedList<>()); - List contributors = dmp.getUsers().stream().map(userDMP -> { - ZenodoContributor contributor = new ZenodoContributor(); - contributor.setName(userDMP.getUser().getName()); - contributor.setType("ProjectMember"); - if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) { - contributor.setAffiliation(dmp.getOrganisations() - .stream().map(Organisation::getLabel).collect(Collectors.joining(", "))); - } else { - contributor.setAffiliation(environment.getProperty("zenodo.affiliation")); - } - return contributor; - }).collect(Collectors.toList()); - - List researchers = dmp.getResearchers().stream().map(researcher -> { - ZenodoContributor contributor = new ZenodoContributor(); - contributor.setName(researcher.getLabel()); - contributor.setType("Researcher"); - String referenceHead = researcher.getReference().split(":")[0]; - String referenceTail = researcher.getReference().replace(referenceHead + ":", ""); - contributor.setAffiliation(referenceHead); - if (referenceHead.equalsIgnoreCase("ORCID")) { - contributor.setOrcid(referenceTail); - } - return contributor; - }).collect(Collectors.toList()); - - deposit.getMetadata().getContributors().addAll(contributors); - deposit.getMetadata().getContributors().addAll(researchers); - - if (dmp.getGrant().getReference() == null) { - dmp.getGrant().setReference("dmp:" + dmp.getGrant().getId()); - } - String grantReferenceHead = dmp.getGrant().getReference().split(":")[0]; - if (grantReferenceHead.equals("openaire")) { - String grantReferenceTail = dmp.getGrant().getReference().split(":")[3]; - DOIFunder doiFunder = configLoader.getDOIFunders().stream() - .filter(doiFunder1 -> dmp.getGrant().getFunder().getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(dmp.getGrant().getFunder().getLabel())) - .findFirst().orElse(null); - if (doiFunder != null) { - String finalId = doiFunder.getDOI() + "::" + grantReferenceTail; - ZenodoGrant grant = new ZenodoGrant(); - grant.setId(finalId); - deposit.getMetadata().setGrants(Collections.singletonList(grant)); - } - } - ZenodoContributor creator = new ZenodoContributor(); - creator.setName(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName()); - if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) { - creator.setAffiliation(dmp.getOrganisations() - .stream().map(Organisation::getLabel).collect(Collectors.joining(", "))); - } else { - creator.setAffiliation(environment.getProperty("zenodo.affiliation")); - } - deposit.getMetadata().setCreators(Collections.singletonList(creator)); - - return deposit; - } -} - diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java b/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java index 539367e10..66ceff6c3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java @@ -47,8 +47,12 @@ public class DmpRDAMapper { } } Dmp rda = new Dmp(); - if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) { - rda.setDmpId(DmpIdRDAMapper.toRDA(dmp.getDoi())); + if (dmp.getDois() != null && !dmp.getDois().isEmpty()) { + for(EntityDoi doi: dmp.getDois()){ + if(doi.getRepositoryId().equals("Zenodo")){ + rda.setDmpId(DmpIdRDAMapper.toRDA(doi.getDoi())); + } + } } else { rda.setDmpId(DmpIdRDAMapper.toRDA(dmp.getId())); } @@ -105,7 +109,10 @@ public class DmpRDAMapper { DMP entity = new DMP(); entity.setLabel(rda.getTitle()); if (rda.getDmpId().getType() == DmpId.Type.DOI) { - entity.setDoi(rda.getDmpId().getIdentifier()); + EntityDoi doi = apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().findFromDoi(rda.getDmpId().getIdentifier()); + Set dois = new HashSet<>(); + dois.add(doi); + entity.setDois(dois); } if (((List) rda.getAdditionalProperties().get("templates")) != null && !((List) rda.getAdditionalProperties().get("templates")).isEmpty()) { entity.setAssociatedDmps(((List) rda.getAdditionalProperties().get("templates")).stream().map(this::getProfile).filter(Objects::nonNull).collect(Collectors.toSet())); diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/doi/DoiPublicModel.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/doi/DoiPublicModel.java new file mode 100644 index 000000000..4b8c5dbae --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/doi/DoiPublicModel.java @@ -0,0 +1,61 @@ +package eu.eudat.publicapi.models.doi; + +import eu.eudat.data.entities.EntityDoi; +import eu.eudat.logic.utilities.helpers.LabelGenerator; +import eu.eudat.models.DataModel; + +import java.util.UUID; + +public class DoiPublicModel implements DataModel, LabelGenerator { + private UUID id; + private String repositoryId; + private String doi; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDoi() { + return doi; + } + public void setDoi(String doi) { + this.doi = doi; + } + + @Override + public DoiPublicModel fromDataModel(EntityDoi entity) { + this.id = entity.getId(); + this.repositoryId = entity.getRepositoryId(); + this.doi = entity.getDoi(); + return this; + } + + @Override + public EntityDoi toDataModel() throws Exception { + EntityDoi entity = new EntityDoi(); + entity.setId(this.getId()); + entity.setRepositoryId(this.getRepositoryId()); + entity.setDoi(this.getDoi()); + return entity; + } + + @Override + public String generateLabel() { + return this.getDoi(); + } + + @Override + public String getHint() { + return null; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java index 6b5040371..41c7b40cd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java @@ -7,6 +7,7 @@ import eu.eudat.logic.utilities.builders.XmlBuilder; import eu.eudat.models.DataModel; import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.publicapi.models.associatedprofile.AssociatedProfilePublicModel; +import eu.eudat.publicapi.models.doi.DoiPublicModel; import eu.eudat.publicapi.models.grant.GrantPublicOverviewModel; import eu.eudat.publicapi.models.organisation.OrganizationPublicModel; import eu.eudat.publicapi.models.researcher.ResearcherPublicModel; @@ -35,7 +36,7 @@ public class DataManagementPlanPublicModel implements DataModel users; private String description; private Date publishedAt; - private String doi; + private List dois; public String getId() { @@ -150,11 +151,11 @@ public class DataManagementPlanPublicModel implements DataModel getDois() { + return dois; } - public void setDoi(String doi) { - this.doi = doi; + public void setDois(List dois) { + this.dois = dois; } @Override @@ -198,7 +199,7 @@ public class DataManagementPlanPublicModel implements DataModel new DoiPublicModel().fromDataModel(item)).collect(Collectors.toList()); return this; } diff --git a/dmp-db-scema/main/dmp-dump.sql b/dmp-db-scema/main/dmp-dump.sql index 1a63a0774..470447770 100644 --- a/dmp-db-scema/main/dmp-dump.sql +++ b/dmp-db-scema/main/dmp-dump.sql @@ -926,6 +926,27 @@ CREATE TABLE public."FileUpload" ALTER TABLE public."FileUpload" OWNER TO :POSTGRES_USER; +-- +-- Name: EntityDoi; Type: TABLE; Schema: public; Owner: :POSTGRES_USER +-- + +CREATE TYPE DoiEntityType AS ENUM ('DMP'); + +CREATE TABLE public."EntityDoi" +( + "ID" uuid NOT NULL, + "EntityType" DoiEntityType NOT NULL, + "RepositoryId" character varying(150) NOT NULL, + "Doi" character varying(50) NOt NULL, + "CreatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "UpdatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "EntityId" uuid NOT NULL, + CONSTRAINT "Doi_pkey" PRIMARY KEY ("ID"), + CONSTRAINT fk_doi_entityId FOREIGN KEY ("EntityId") REFERENCES public."DMP"("ID") +); + +ALTER TABLE public."EntityDoi" OWNER TO :POSTGRES_USER; + -- -- Name: Content Content_pkey; Type: CONSTRAINT; Schema: public; Owner: :POSTGRES_USER -- diff --git a/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql b/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql new file mode 100644 index 000000000..d92e9d1d8 --- /dev/null +++ b/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql @@ -0,0 +1,26 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.00.010'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + +CREATE TYPE DoiEntityType AS ENUM ('DMP'); + +CREATE TABLE public."EntityDoi" +( + "ID" uuid NOT NULL, + "EntityType" DoiEntityType NOT NULL, + "RepositoryId" character varying(150) NOT NULL, + "Doi" character varying(50) NOt NULL, + "CreatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "UpdatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "EntityId" uuid NOT NULL, + CONSTRAINT "Doi_pkey" PRIMARY KEY ("ID"), + CONSTRAINT fk_doi_entityId FOREIGN KEY ("EntityId") REFERENCES public."DMP"("ID") +); + +/*ALTER TABLE public."EntityDoi" OWNER TO :POSTGRES_USER;*/ + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.010', '2022-10-27 10:50:00.000000+02', now(), 'Add Doi Table for depositions'); + +END$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql b/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql new file mode 100644 index 000000000..6189fe51a --- /dev/null +++ b/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql @@ -0,0 +1,14 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.00.011'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + +INSERT INTO public."EntityDoi" ("ID", "EntityType", "RepositoryId", "Doi", "CreatedAt", "UpdatedAt", "EntityId") +SELECT uuid_generate_v4(), 'DMP', 'Zenodo', public."DMP"."DOI", now(), now(), public."DMP"."ID" +FROM public."DMP" +WHERE public."DMP"."DOI" IS NOT NULL; + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.011', '2022-10-27 10:50:00.000000+02', now(), 'Migrate DMP.DOI to EntityDoi table'); + +END$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql b/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql new file mode 100644 index 000000000..0a57ff8ab --- /dev/null +++ b/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql @@ -0,0 +1,11 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.00.012'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + +ALTER TABLE public."DMP" DROP COLUMN "DOI"; + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.012', '2022-10-27 10:50:00.000000+02', now(), 'Delete doi column from dmp table'); + +END$$; \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts b/dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts new file mode 100644 index 000000000..fc5787572 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts @@ -0,0 +1,5 @@ +export enum DepositConfigurationStatus { + System = 0, + User = 1, + BothSystemAndUser = 2 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts index 6f81f1095..b36cf42f8 100644 --- a/dmp-frontend/src/app/core/core-service.module.ts +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -46,6 +46,7 @@ import { CollectionUtils } from './services/utilities/collection-utils.service'; import { TypeUtils } from './services/utilities/type-utils.service'; import { SpecialAuthGuard } from './special-auth-guard.service'; import {PrefillingService} from "@app/core/services/prefilling.service"; +import { DepositRepositoriesService } from './services/deposit-repositories/deposit-repositories.service'; // // // This is shared module that provides all the services. Its imported only once on the AppModule. @@ -89,6 +90,7 @@ export class CoreServiceModule { FunderService, GrantFileUploadService, DmpService, + DepositRepositoriesService, DmpProfileService, ExternalSourcesService, ExternalSourcesConfigurationService, diff --git a/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts b/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts new file mode 100644 index 000000000..bfcc105c6 --- /dev/null +++ b/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts @@ -0,0 +1,10 @@ +import { DepositConfigurationStatus } from "@app/core/common/enum/deposit-configuration-status"; + +export class DepositConfigurationModel { + depositType: DepositConfigurationStatus; + repositoryId: string; + repositoryAuthorizationUrl: string; + repositoryRecordUrl: string; + repositoryClientId: string; + redirectUri: string; +} diff --git a/dmp-frontend/src/app/core/model/deposit/deposit-request.ts b/dmp-frontend/src/app/core/model/deposit/deposit-request.ts new file mode 100644 index 000000000..10ee13980 --- /dev/null +++ b/dmp-frontend/src/app/core/model/deposit/deposit-request.ts @@ -0,0 +1,10 @@ +export class DepositRequest { + repositoryId: string; + dmpId: string; + accessToken: string; +} + +export class DepositCode { + repositoryId: string; + code: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts b/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts index da5802817..a5171ad61 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts @@ -4,6 +4,7 @@ import { DmpAssociatedProfileModel } from "../dmp-profile/dmp-associated-profile import { ResearcherModel } from "../researcher/researcher"; import { GrantOverviewModel } from "../grant/grant-overview"; import { DatasetOverviewModel } from "../dataset/dataset-overview"; +import { DoiModel } from "../doi/doi"; export interface DmpOverviewModel { id: string; @@ -26,4 +27,5 @@ export interface DmpOverviewModel { finalizedAt: Date; publishedAt: Date; doi: string; + dois: DoiModel[]; } diff --git a/dmp-frontend/src/app/core/model/doi/doi.ts b/dmp-frontend/src/app/core/model/doi/doi.ts new file mode 100644 index 000000000..c72ba0023 --- /dev/null +++ b/dmp-frontend/src/app/core/model/doi/doi.ts @@ -0,0 +1,7 @@ +export interface DoiModel { + id: string; + repositoryId: string; + doi: string; + createdAt: Date; + updatedAt: Date; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index 9b92ad064..64082cb55 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -66,11 +66,6 @@ export class ConfigurationService extends BaseComponent { return this._allowOrganizationCreator; } - private _doiLink: string; - get doiLink(): string { - return this._doiLink; - } - private _useSplash: string; get useSplash(): string { return this._useSplash; @@ -137,7 +132,6 @@ export class ConfigurationService extends BaseComponent { this._lockInterval = config.lockInterval; this._guideAssets = config.guideAssets; this._allowOrganizationCreator = config.allowOrganizationCreator; - this._doiLink = config.doiLink; this._useSplash = config.useSplash; this._orcidPath = config.orcidPath; if (config.matomo) { diff --git a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts new file mode 100644 index 000000000..235f766a8 --- /dev/null +++ b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts @@ -0,0 +1,38 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; +import { DepositCode, DepositRequest } from '@app/core/model/deposit/deposit-request'; +import { DoiModel } from '@app/core/model/doi/doi'; +import { Observable } from 'rxjs'; +import { ConfigurationService } from '../configuration/configuration.service'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DepositRepositoriesService { + + private actionUrl: string; + private headers = new HttpHeaders(); + + constructor(private http: BaseHttpService, private httpClient: HttpClient, private configurationService: ConfigurationService) { + this.actionUrl = configurationService.server + 'deposit/'; + } + + getAvailableRepos(): Observable { + return this.http.get(this.actionUrl + 'repos', { headers: this.headers }); + } + + getAccessToken(repositoryId: string, code: string): Observable { + const depositCode = new DepositCode(); + depositCode.repositoryId = repositoryId; + depositCode.code = code; + return this.http.post(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers }); + } + + createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable { + const depositRequest = new DepositRequest(); + depositRequest.repositoryId = repositoryId; + depositRequest.dmpId = dmpId; + depositRequest.accessToken = accessToken; + return this.http.post(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp.module.ts b/dmp-frontend/src/app/ui/dmp/dmp.module.ts index 01f0355b6..16867c162 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp.module.ts @@ -50,6 +50,7 @@ import { FormProgressIndicationComponent } from '../misc/dataset-description-for import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module'; import { DatasetPreviewDialogComponent } from './dataset-preview/dataset-preview-dialog.component'; import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-editor.module"; +import { DmpDepositDialogComponent } from './editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; @NgModule({ imports: [ @@ -103,7 +104,8 @@ import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-edit FundingInfoComponent, DatasetInfoComponent, LicenseInfoComponent, - DatasetPreviewDialogComponent + DatasetPreviewDialogComponent, + DmpDepositDialogComponent ], entryComponents: [ DmpInvitationDialogComponent, @@ -119,7 +121,8 @@ import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-edit StartNewDmpDialogComponent, StartNewDatasetDialogComponent, DatasetEditorDetailsComponent, - DatasetPreviewDialogComponent + DatasetPreviewDialogComponent, + DmpDepositDialogComponent ] }) export class DmpModule { } diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html new file mode 100644 index 000000000..1ab72528e --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html @@ -0,0 +1,21 @@ +
+
{{ data.message }}
+
+ close +
+
+
+ + + +
+
{{'DMP-OVERVIEW.DEPOSIT.NO-REPOSITORIES' | translate}}
+ +
+
+ +
+ +
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts new file mode 100644 index 000000000..5254b633b --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -0,0 +1,138 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { DepositConfigurationStatus } from '@app/core/common/enum/deposit-configuration-status'; +import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; +import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; +import { DoiModel } from '@app/core/model/doi/doi'; +import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service'; +import { BaseComponent } from '@common/base/base.component'; +import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-dmp-deposit-dialog', + templateUrl: './dmp-deposit-dialog.component.html', + styleUrls: ['./dmp-deposit-dialog.component.scss'] +}) +export class DmpDepositDialogComponent extends BaseComponent implements OnInit { + + inputRepos: DepositConfigurationModel[]; + outputRepos: DoiModel[]; + dmp: DmpOverviewModel; + private oauthLock: boolean; + + constructor( + private depositRepositoriesService: DepositRepositoriesService, + public dialogRef: MatDialogRef, + private dialog: MatDialog, + private language: TranslateService, + private translate: TranslateService, + private uiNotificationService: UiNotificationService, + private oauth2DialogService: Oauth2DialogService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + super(); + this.inputRepos = data['depositRepos'][0]; + this.dmp = data['depositRepos'][1]; + for(var i = 0; i < this.dmp.dois.length; i++){ + this.inputRepos = this.inputRepos.filter(r => this.hasDoi(r, this.dmp.dois, i)); + } + this.outputRepos = []; + } + + hasDoi(repo, dois, i){ + return repo.repositoryId !== dois[i].repositoryId; + } + + ngOnInit(): void { + } + + onSubmit() { + this.dialogRef.close(this.outputRepos); + } + + close() { + this.dialogRef.close(this.outputRepos); + } + + deposit(repo: DepositConfigurationModel) { + + if(repo.depositType == DepositConfigurationStatus.BothSystemAndUser){ + + const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, { + maxWidth: '600px', + restoreFocus: false, + data: { + message: this.language.instant('DMP-OVERVIEW.DEPOSIT.ACCOUNT-LOGIN'), + titles: [this.language.instant('DMP-OVERVIEW.DEPOSIT.LOGIN', { 'repository': repo.repositoryId }), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + switch (result) { + case 0: + this.showOauth2Dialog(repo.repositoryAuthorizationUrl + '?client_id=' + repo.repositoryClientId + + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' + + repo.redirectUri, repo, this.dmp); + break; + case 1: + this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null) + .pipe(takeUntil(this._destroyed)) + .subscribe(doi =>{ + this.onDOICallbackSuccess(); + this.outputRepos.push(doi); + this.close(); + }, error => this.onDOICallbackError(error)); + break; + } + }); + + } + else if(repo.depositType == DepositConfigurationStatus.System){ + this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null) + .pipe(takeUntil(this._destroyed)) + .subscribe(doi =>{ + this.onDOICallbackSuccess(); + this.outputRepos.push(doi); + this.close(); + }, error => this.onDOICallbackError(error)); + } + } + + onDOICallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success); + } + + onDOICallbackError(error) { + this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error); + } + + showOauth2Dialog(url: string, repo: DepositConfigurationModel, dmp: DmpOverviewModel) { + this.oauth2DialogService.login(url) + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (result !== undefined) { + if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) { + this.depositRepositoriesService.getAccessToken(repo.repositoryId, result.oauthCode) + .pipe(takeUntil(this._destroyed)) + .subscribe(token => { + this.depositRepositoriesService.createDoi(repo.repositoryId, dmp.id, token) + .pipe(takeUntil(this._destroyed)) + .subscribe(doi =>{ + this.onDOICallbackSuccess(); + this.outputRepos.push(doi); + this.close(); + }, error => this.onDOICallbackError(error)); + }); + this.oauthLock = true; + } + } + else{ + this.oauthLock = false; + } + }); + } + +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts index 007dfa991..4c6a8bc76 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -980,7 +980,8 @@ export class DmpEditorComponent extends CheckDeactivateBaseComponent implements dmpDescription: this.formGroup.get('description').value, datasets: this.formGroup.get('datasets').value.map(x => { return { label: x.label, id: x.id, status: x.status }; - }) + }), + accessRights: false } const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, { diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html index 634ea89e8..a19f9cc0d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html @@ -64,8 +64,11 @@
{{ 'DMP-FINALISE-DIALOG.IMPACT' | translate }}
-
- {{ 'DMP-FINALISE-DIALOG.AFTER-FINALIZATION' | translate }} +
+ {{ 'DMP-FINALISE-DIALOG.AFTER-FINALIZATION-PUBLISH' | translate }} +
+
+ {{ 'DMP-FINALISE-DIALOG.AFTER-FINALIZATION-RESTRICT-ACCESS' | translate }}
diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts index f16ff8747..dd8b27e34 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts @@ -95,6 +95,7 @@ export interface DmpFinalizeDialogInput { dmpLabel: string; dmpDescription: string; datasets: DmpFinalizeDialogDataset[]; + accessRights: boolean; } export interface DmpFinalizeDialogDataset { diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index c0efb9577..ef03de5fe 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -114,21 +114,41 @@

{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}

-

- -

-
-
+
@@ -141,7 +161,7 @@
-
+
@@ -167,12 +187,12 @@

{{ 'DMP-LISTING.ACTIONS.START-NEW-VERSION' | translate }}

-
+