[WIP] EntityDoi table

This commit is contained in:
Bernaldo Mihasi 2022-11-02 09:41:40 +02:00
parent 7d624a2daa
commit 59e26dbb8d
22 changed files with 498 additions and 43 deletions

View File

@ -0,0 +1,9 @@
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, UUID> {
}

View File

@ -0,0 +1,51 @@
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<EntityDoi> implements EntityDoiDao {
@Autowired
public EntityDoiDaoImpl(DatabaseService<EntityDoi> databaseService){
super(databaseService);
}
@Override
public EntityDoi createOrUpdate(EntityDoi item) {
return this.getDatabaseService().createOrUpdate(item, EntityDoi.class);
}
@Override
public CompletableFuture<EntityDoi> 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 find(UUID id, String hint) {
return null;
}
@Override
public void delete(EntityDoi item) {
this.getDatabaseService().delete(item);
}
@Override
public QueryableList<EntityDoi> asQueryable() {
return this.getDatabaseService().getQueryable(EntityDoi.class);
}
}

View File

@ -184,6 +184,9 @@ public class DMP implements DataEntity<DMP, UUID> {
@Column(name = "\"DOI\"") @Column(name = "\"DOI\"")
private String doi; private String doi;
@OneToMany(mappedBy = "entityId", fetch = FetchType.LAZY)
private Set<EntityDoi> dois;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "\"Project\"") @JoinColumn(name = "\"Project\"")
private Project project; private Project project;
@ -346,6 +349,13 @@ public class DMP implements DataEntity<DMP, UUID> {
this.doi = doi; this.doi = doi;
} }
public Set<EntityDoi> getDois() {
return dois;
}
public void setDois(Set<EntityDoi> dois) {
this.dois = dois;
}
public Project getProject() { public Project getProject() {
return project; return project;
} }
@ -381,6 +391,7 @@ public class DMP implements DataEntity<DMP, UUID> {
if (entity.isPublic) this.setPublishedAt(new Date()); if (entity.isPublic) this.setPublishedAt(new Date());
if (entity.getUsers() != null) this.users = entity.getUsers(); if (entity.getUsers() != null) this.users = entity.getUsers();
if (entity.getDoi() != null && entity.getDoi().trim().isEmpty()) this.doi = entity.doi; if (entity.getDoi() != null && entity.getDoi().trim().isEmpty()) this.doi = entity.doi;
this.dois = entity.getDois();
this.extraProperties = entity.getExtraProperties(); this.extraProperties = entity.getExtraProperties();
} }

View File

@ -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<EntityDoi, UUID> {
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> tuple, List<String> 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;
}
}

View File

@ -6,6 +6,7 @@ import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.doi.DepositCode; import eu.eudat.models.data.doi.DepositCode;
import eu.eudat.models.data.doi.DepositRequest; import eu.eudat.models.data.doi.DepositRequest;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import eu.eudat.types.ApiMessageCode; import eu.eudat.types.ApiMessageCode;
@ -49,13 +50,13 @@ public class DepositController extends BaseController {
@RequestMapping(method = RequestMethod.POST, value = {"/createDoi"}) @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"})
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<String>> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { ResponseEntity<ResponseItem<Doi>> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
try { try {
String doi = this.depositManager.deposit(depositRequest, principal); Doi doi = this.depositManager.deposit(depositRequest, principal);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Doi>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi));
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Doi>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage()));
} }
} }
} }

View File

@ -49,6 +49,7 @@ import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized; import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized;
import eu.eudat.models.data.dmp.*; import eu.eudat.models.data.dmp.*;
import eu.eudat.models.data.doi.DepositRequest; 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.dynamicfields.DynamicFieldWithValue;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field;
@ -2104,7 +2105,7 @@ public class DataManagementPlanManager {
return finalDoi; return finalDoi;
} }
public String createDoi(DepositRequest depositRequest, Principal principal) throws Exception { public Doi createDoi(DepositRequest depositRequest, Principal principal) throws Exception {
DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId())); DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId()));
if (!isUserOwnerOfDmp(dmp, principal)) if (!isUserOwnerOfDmp(dmp, principal))
throw new Exception("User is not authorized to invoke this action"); throw new Exception("User is not authorized to invoke this action");
@ -2150,13 +2151,29 @@ public class DataManagementPlanManager {
return null; return null;
} }
}).orElse(null); }).orElse(null);
Doi doiModel = null;
if (finalDoi != null) { if (finalDoi != null) {
dmp.setDoi(finalDoi);
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); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
doiModel = new Doi().fromDataModel(doiEntity);
} }
Files.deleteIfExists(file.getFile().toPath()); Files.deleteIfExists(file.getFile().toPath());
return finalDoi; return doiModel;
} }
/* /*

View File

@ -9,6 +9,7 @@ import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
import eu.eudat.logic.utilities.documents.pdf.PDFUtils; import eu.eudat.logic.utilities.documents.pdf.PDFUtils;
import eu.eudat.models.data.doi.DepositRequest; import eu.eudat.models.data.doi.DepositRequest;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -56,7 +57,7 @@ public class DepositManager {
return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null); return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null);
} }
public String deposit(DepositRequest depositRequest, Principal principal) throws Exception { public Doi deposit(DepositRequest depositRequest, Principal principal) throws Exception {
return this.dataManagementPlanManager.createDoi(depositRequest, principal); return this.dataManagementPlanManager.createDoi(depositRequest, principal);
} }
} }

View File

@ -60,5 +60,7 @@ public interface DatabaseRepository {
FileUploadDao getFileUploadDao(); FileUploadDao getFileUploadDao();
EntityDoiDao getEntityDoiDao();
<T> void detachEntity(T entity); <T> void detachEntity(T entity);
} }

View File

@ -39,6 +39,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
private LockDao lockDao; private LockDao lockDao;
private NotificationDao notificationDao; private NotificationDao notificationDao;
private FileUploadDao fileUploadDao; private FileUploadDao fileUploadDao;
private EntityDoiDao entityDoiDao;
private EntityManager entityManager; private EntityManager entityManager;
@ -317,6 +318,15 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
this.fileUploadDao = fileUploadDao; this.fileUploadDao = fileUploadDao;
} }
@Override
public EntityDoiDao getEntityDoiDao() {
return entityDoiDao;
}
@Autowired
public void setEntityDoiDao(EntityDoiDao entityDoiDao) {
this.entityDoiDao = entityDoiDao;
}
public <T> void detachEntity(T entity) { public <T> void detachEntity(T entity) {
this.entityManager.detach(entity); this.entityManager.detach(entity);

View File

@ -4,6 +4,7 @@ import eu.eudat.data.entities.*;
import eu.eudat.logic.utilities.builders.XmlBuilder; import eu.eudat.logic.utilities.builders.XmlBuilder;
import eu.eudat.models.DataModel; import eu.eudat.models.DataModel;
import eu.eudat.models.data.datasetwizard.DatasetWizardModel; 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.dynamicfields.DynamicFieldWithValue;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile;
import eu.eudat.models.data.funder.Funder; import eu.eudat.models.data.funder.Funder;
@ -41,6 +42,7 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
private Map<String, Object> properties; private Map<String, Object> properties;
private List<UserInfoListingModel> users; private List<UserInfoListingModel> users;
private String doi; private String doi;
private List<Doi> dois;
private Project project; private Project project;
private Funder funder; private Funder funder;
private Boolean isPublic; private Boolean isPublic;
@ -201,6 +203,13 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
this.doi = doi; this.doi = doi;
} }
public List<Doi> getDois() {
return dois;
}
public void setDois(List<Doi> dois) {
this.dois = dois;
}
public Project getProject() { public Project getProject() {
return project; return project;
} }
@ -281,6 +290,7 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>(); 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.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>();
this.doi = entity.getDoi(); 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) { if (entity.getProject() != null) {
this.project = new Project(); this.project = new Project();
@ -377,6 +387,7 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>(); 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.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>();
this.doi = entity.getDoi(); 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()); this.grant.fromDataModel(entity.getGrant());
if (entity.getProject() != null) { if (entity.getProject() != null) {

View File

@ -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<EntityDoi, Doi> {
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;
}
}

View File

@ -8,6 +8,7 @@ import eu.eudat.models.data.dataset.DatasetOverviewModel;
import eu.eudat.models.data.dmp.AssociatedProfile; import eu.eudat.models.data.dmp.AssociatedProfile;
import eu.eudat.models.data.dmp.Organisation; import eu.eudat.models.data.dmp.Organisation;
import eu.eudat.models.data.dmp.Researcher; import eu.eudat.models.data.dmp.Researcher;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.grant.GrantOverviewModel; import eu.eudat.models.data.grant.GrantOverviewModel;
import java.util.Date; import java.util.Date;
@ -36,6 +37,7 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
private boolean isPublic; private boolean isPublic;
private Date publishedAt; private Date publishedAt;
private String doi; private String doi;
private List<Doi> dois;
public String getId() { public String getId() {
@ -171,6 +173,13 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
this.doi = doi; this.doi = doi;
} }
public List<Doi> getDois() {
return dois;
}
public void setDois(List<Doi> dois) {
this.dois = dois;
}
@Override @Override
public DataManagementPlanOverviewModel fromDataModel(DMP entity) { public DataManagementPlanOverviewModel fromDataModel(DMP entity) {
this.id = entity.getId().toString(); this.id = entity.getId().toString();
@ -180,6 +189,9 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
if (entity.getResearchers() != null) { if (entity.getResearchers() != null) {
this.researchers = entity.getResearchers().stream().map(item -> new Researcher().fromDataModel(item)).collect(Collectors.toList()); this.researchers = entity.getResearchers().stream().map(item -> 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; return this;
} }
@ -209,6 +221,7 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
this.isPublic = entity.isPublic(); this.isPublic = entity.isPublic();
this.publishedAt = entity.getPublishedAt(); this.publishedAt = entity.getPublishedAt();
this.doi = entity.getDoi(); this.doi = entity.getDoi();
this.dois = entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList());
return this; return this;
} }

View File

@ -926,6 +926,27 @@ CREATE TABLE public."FileUpload"
ALTER TABLE public."FileUpload" OWNER TO :POSTGRES_USER; 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 -- Name: Content Content_pkey; Type: CONSTRAINT; Schema: public; Owner: :POSTGRES_USER
-- --

View File

@ -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$$;

View File

@ -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$$;

View File

@ -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$$;

View File

@ -4,6 +4,7 @@ import { DmpAssociatedProfileModel } from "../dmp-profile/dmp-associated-profile
import { ResearcherModel } from "../researcher/researcher"; import { ResearcherModel } from "../researcher/researcher";
import { GrantOverviewModel } from "../grant/grant-overview"; import { GrantOverviewModel } from "../grant/grant-overview";
import { DatasetOverviewModel } from "../dataset/dataset-overview"; import { DatasetOverviewModel } from "../dataset/dataset-overview";
import { DoiModel } from "../doi/doi";
export interface DmpOverviewModel { export interface DmpOverviewModel {
id: string; id: string;
@ -26,4 +27,5 @@ export interface DmpOverviewModel {
finalizedAt: Date; finalizedAt: Date;
publishedAt: Date; publishedAt: Date;
doi: string; doi: string;
dois: DoiModel[];
} }

View File

@ -0,0 +1,7 @@
export interface DoiModel {
id: string;
repositoryId: string;
doi: string;
createdAt: Date;
updatedAt: Date;
}

View File

@ -2,6 +2,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration';
import { DepositCode, DepositRequest } from '@app/core/model/deposit/deposit-request'; import { DepositCode, DepositRequest } from '@app/core/model/deposit/deposit-request';
import { DoiModel } from '@app/core/model/doi/doi';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ConfigurationService } from '../configuration/configuration.service'; import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpService } from '../http/base-http.service'; import { BaseHttpService } from '../http/base-http.service';
@ -27,11 +28,11 @@ export class DepositRepositoriesService {
return this.http.post<string>(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers }); return this.http.post<string>(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers });
} }
createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable<string> { createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable<DoiModel> {
const depositRequest = new DepositRequest(); const depositRequest = new DepositRequest();
depositRequest.repositoryId = repositoryId; depositRequest.repositoryId = repositoryId;
depositRequest.dmpId = dmpId; depositRequest.dmpId = dmpId;
depositRequest.accessToken = accessToken; depositRequest.accessToken = accessToken;
return this.http.post<string>(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); return this.http.post<DoiModel>(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers });
} }
} }

View File

@ -3,6 +3,7 @@ import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dial
import { DepositConfigurationStatus } from '@app/core/common/enum/deposit-configuration-status'; import { DepositConfigurationStatus } from '@app/core/common/enum/deposit-configuration-status';
import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration';
import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; 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 { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service';
import { DmpService } from '@app/core/services/dmp/dmp.service'; import { DmpService } from '@app/core/services/dmp/dmp.service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
@ -21,7 +22,7 @@ import { takeUntil } from 'rxjs/operators';
export class DmpDepositDialogComponent extends BaseComponent implements OnInit { export class DmpDepositDialogComponent extends BaseComponent implements OnInit {
inputRepos: DepositConfigurationModel[]; inputRepos: DepositConfigurationModel[];
outputRepos: string[]; outputRepos: DoiModel[];
dmp: DmpOverviewModel; dmp: DmpOverviewModel;
constructor( constructor(
@ -37,9 +38,16 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit {
super(); super();
this.inputRepos = data['depositRepos'][0]; this.inputRepos = data['depositRepos'][0];
this.dmp = data['depositRepos'][1]; 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 = []; this.outputRepos = [];
} }
hasDoi(repo, dois, i){
return repo.repositoryId !== dois[i].repositoryId;
}
ngOnInit(): void { ngOnInit(): void {
} }
@ -76,6 +84,10 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit {
.subscribe(doi =>{ .subscribe(doi =>{
this.onDOICallbackSuccess(); this.onDOICallbackSuccess();
this.outputRepos.push(doi); this.outputRepos.push(doi);
this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; });
if(this.inputRepos.length == 0){
this.close();
}
}, error => this.onDeleteCallbackError(error)); }, error => this.onDeleteCallbackError(error));
break; break;
} }
@ -106,6 +118,10 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit {
.subscribe(doi =>{ .subscribe(doi =>{
this.onDOICallbackSuccess(); this.onDOICallbackSuccess();
this.outputRepos.push(doi); this.outputRepos.push(doi);
this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; });
if(this.inputRepos.length == 0){
this.close();
}
}, error => this.onDeleteCallbackError(error)); }, error => this.onDeleteCallbackError(error));
}); });
// this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2')

View File

@ -114,21 +114,41 @@
<div *ngIf="!hasDoi(dmp)" class="row d-flex flex-column ml-0 mr-0 mb-3"> <div *ngIf="!hasDoi(dmp)" class="row d-flex flex-column ml-0 mr-0 mb-3">
<p class="doi-label">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}</p> <p class="doi-label">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}</p>
<div class="doi-panel"> <div class="doi-panel">
<p *ngIf="!hasDoi(dmp)" class="mb-0 ml-3"> <mat-select class="mb-0 ml-3" placeholder="{{ dmp.dois[0].doi }}">
<textarea #doi class="doi-txt">{{ dmp.doi }}</textarea> <mat-option *ngFor="let x of dmp.dois">
</p> {{x.repositoryId}}
<div class="d-flex justify-content-end"> </mat-option>
</mat-select>
<div class="d-flex justify-content-end ml-3">
<button (click)="copyDoi(doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above"> <button (click)="copyDoi(doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon> <mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
</button> </button>
<button mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above"> <button mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<a [href]="createDoiLink(dmp.doi)" class="doi-link" target="_blank"> <a [href]="createDoiLink(dmp.dois[0].doi)" class="doi-link" target="_blank">
<mat-icon class="mat-mini-fab-icon">launch</mat-icon> <mat-icon class="mat-mini-fab-icon">launch</mat-icon>
</a> </a>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<!-- <div *ngIf="!hasDoi(dmp)" class="row d-flex flex-column ml-0 mr-0 mb-3">
<p class="doi-label">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}</p>
<div class="doi-panel">
<p *ngIf="!hasDoi(dmp)" class="mb-0 ml-3">
<textarea #doi class="doi-txt">{{ dmp.dois[0].doi }}</textarea>
</p>
<div class="d-flex justify-content-end">
<button (click)="copyDoi(doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
</button>
<button mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<a [href]="createDoiLink(dmp.dois[0].doi)" class="doi-link" target="_blank">
<mat-icon class="mat-mini-fab-icon">launch</mat-icon>
</a>
</button>
</div>
</div>
</div> -->
<div class="frame mb-3 pt-4 pl-3 pr-5 pb-1"> <div class="frame mb-3 pt-4 pl-3 pr-5 pb-1">
<div *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus"> <div *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus">
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(dmp)"> <div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(dmp)">
@ -141,7 +161,7 @@
<hr class="hr-line"> <hr class="hr-line">
</div> </div>
</div> </div>
<div *ngIf="hasDoi(dmp) && isFinalizedDmp(dmp) && !this.isPublicView && isUserOwner" (click)="deposit()" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center"> <div *ngIf="(hasDoi(dmp) || moreDeposit()) && isFinalizedDmp(dmp) && !this.isPublicView && isUserOwner" (click)="deposit()" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<button mat-mini-fab class="frame-btn"> <button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">archive</mat-icon> <mat-icon class="mat-mini-fab-icon">archive</mat-icon>
</button> </button>

View File

@ -44,6 +44,7 @@ import { PopupNotificationDialogComponent } from '@app/library/notification/popu
import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service';
import { DmpDepositDialogComponent } from '../editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; import { DmpDepositDialogComponent } from '../editor/dmp-deposit-dialog/dmp-deposit-dialog.component';
import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration';
import { DoiModel } from '@app/core/model/doi/doi';
@Component({ @Component({
selector: 'app-dmp-overview', selector: 'app-dmp-overview',
@ -71,7 +72,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
@ViewChild('doi') @ViewChild('doi')
doi: ElementRef; doi: ElementRef;
depositRepos: DepositConfigurationModel[]; depositRepos: DepositConfigurationModel[] = [];
formGroup: FormGroup; formGroup: FormGroup;
@ -151,6 +152,12 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
}); });
} }
}); });
this.depositRepositoriesService.getAvailableRepos()
.pipe(takeUntil(this._destroyed))
.subscribe(
repos => {
this.depositRepos = repos;
});
} }
onFetchingDeletedCallbackError(redirectRoot: string) { onFetchingDeletedCallbackError(redirectRoot: string) {
@ -450,7 +457,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
} }
hasDoi(dmp: DmpOverviewModel) { hasDoi(dmp: DmpOverviewModel) {
return dmp.doi == null ? true : false; return (this.dmp.dois == null || this.dmp.dois.length == 0) ? true : false;
} }
getAccessUrl(): string { getAccessUrl(): string {
@ -585,30 +592,28 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
} }
deposit(){ deposit(){
this.depositRepositoriesService.getAvailableRepos() const dialogRef = this.dialog.open(DmpDepositDialogComponent, {
.pipe(takeUntil(this._destroyed)) maxWidth: '600px',
.subscribe( disableClose: true,
repos => { restoreFocus: false,
this.depositRepos = repos; autoFocus: false,
const dialogRef = this.dialog.open(DmpDepositDialogComponent, { data: {
maxWidth: '600px', depositRepos: [this.depositRepos, this.dmp],
restoreFocus: false, message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'),
autoFocus: false, confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'),
data: { cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
depositRepos: [this.depositRepos, this.dmp], }
message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), });
confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DoiModel[]) => {
cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), if (result.length > 0) {
} this.dmp.dois.push(...result);
}); this.hasDOIToken = true;
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: string[]) => { }
if (result) { });
this.dmp.doi = result[0]; }
this.hasDOIToken = true;
} moreDeposit(){
}); return (this.dmp.dois.length < this.depositRepos.length) ? true : false;
}
);
} }
finalize(dmp: DmpOverviewModel) { finalize(dmp: DmpOverviewModel) {