repository-deposit-zenodo/core/src/main/java/eu/eudat/depositinterface/zenodorepository/model/builder/ZenodoBuilder.java

320 lines
16 KiB
Java

package eu.eudat.depositinterface.zenodorepository.model.builder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.depositinterface.enums.DmpAccessType;
import eu.eudat.depositinterface.enums.DmpUserRole;
import eu.eudat.depositinterface.enums.ReferenceType;
import eu.eudat.depositinterface.models.*;
import eu.eudat.depositinterface.models.reference.FieldDepositModel;
import eu.eudat.depositinterface.zenodorepository.configuration.funder.FunderProperties;
import eu.eudat.depositinterface.zenodorepository.configuration.identifier.IdentifierProperties;
import eu.eudat.depositinterface.zenodorepository.configuration.pid.PidProperties;
import eu.eudat.depositinterface.zenodorepository.configuration.zenodo.ZenodoProperties;
import eu.eudat.depositinterface.zenodorepository.enums.ZenodoAccessRight;
import eu.eudat.depositinterface.zenodorepository.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ZenodoBuilder {
private static final String UPLOAD_TYPE = "publication";
private static final String PUBLICATION_TYPE = "datamanagementplan";
private static final String IS_IDENTICAL_TO = "isIdenticalTo";
private static final String CONTRIBUTOR_TYPE_RESEARCHER = "Researcher";
private static final String CONTRIBUTOR_TYPE_PROJECT_MANAGER = "ProjectMember";
private static final String SOURCE_OPENAIRE = "openaire";
private static final String SOURCE_ORCID = "ORCID";
private static final String PID = "pid";
private final PidProperties pidProperties;
private final IdentifierProperties identifierProperties;
private final FunderProperties funderProperties;
@Autowired
public ZenodoBuilder(PidProperties pidProperties, IdentifierProperties identifierProperties, FunderProperties funderProperties){
this.pidProperties = pidProperties;
this.identifierProperties = identifierProperties;
this.funderProperties = funderProperties;
}
public ZenodoDeposit build(DmpDepositModel dmp, ZenodoProperties zenodoConfig) throws JsonProcessingException {
ZenodoDeposit deposit = new ZenodoDeposit();
this.applyZenodoRelator(dmp, deposit);
deposit.getMetadata().setTitle(dmp.getLabel());
deposit.getMetadata().setUploadType(UPLOAD_TYPE);
deposit.getMetadata().setPublicationType(PUBLICATION_TYPE);
deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "<p></p>"));
deposit.getMetadata().setVersion(String.valueOf(dmp.getVersion()));
String zenodoCommunity = zenodoConfig.getCommunity();
if(zenodoCommunity != null && !zenodoCommunity.isEmpty()) {
ZenodoCommunity community = new ZenodoCommunity();
community.setIdentifier(zenodoCommunity);
deposit.getMetadata().getCommunities().add(community);
}
this.applyAccessRight(dmp, deposit);
this.applyIsIdenticalTo(dmp, deposit, zenodoConfig);
this.applyLicenses(dmp, deposit);
this.applyResearchers(dmp, deposit);
this.applyGrants(dmp, deposit);
this.applyContributors(dmp, deposit, zenodoConfig);
this.applyCreators(dmp, deposit, zenodoConfig);
return deposit;
}
private List<DescriptionFieldDepositModel> findSchematicValues(String relatedId, List<DescriptionFieldDepositModel> fields){
return fields.stream().filter(f -> f.getSchematics().contains(relatedId)).collect(Collectors.toList());
}
private Set<String> extractSchematicValues(List<DescriptionFieldDepositModel> fields, List<String> acceptedPidTypes) throws JsonProcessingException{
ObjectMapper objectMapper = new ObjectMapper();
Set<String> values = new HashSet<>();
for(DescriptionFieldDepositModel field: fields){
//TODO: Check how to parse this values after update the logic of description persist from the main app
List<String> value =field.getValues() == null ? new ArrayList<>() : field.getValues().stream().map(x-> (String)x).filter(x-> x == null || x.isEmpty()).toList();
if(!value.isEmpty()) {
switch (field.getFieldType()) {
case FREE_TEXT:
case TEXT_AREA:
case RICH_TEXT_AREA:
case RADIO_BOX:
case DATE_PICKER:
case AUTO_COMPLETE:
case WORD_LIST:
values.addAll(value);
break;
case SERVICES:
case EXTERNAL_DATASETS:
case DATA_REPOSITORIES:
case PUB_REPOSITORIES:
case JOURNAL_REPOSITORIES:
case TAXONOMIES:
case PUBLICATIONS:
for (String s : value) {
Map<String, String> valueMap = objectMapper.readValue(s, new TypeReference<Map<String, String>>() {
});
String pid = valueMap.get(this.pidProperties.getFields().getPidName());
String pidType = valueMap.get(this.pidProperties.getFields().getPidTypeName());
if (acceptedPidTypes.contains(pidType)) {
values.add(pid);
}
}
break;
case ORGANIZATIONS:
case RESEARCHERS:
for (String s : value) {
Map<String, String> valueMap = objectMapper.readValue(s, new TypeReference<Map<String, String>>() {});
String pid = valueMap.get("reference");
if(pid != null) {
values.add(pid);
}
}
break;
case DATASET_IDENTIFIER:
for (String s : value) {
Map<String, String> valueMap = objectMapper.readValue(s, new TypeReference<Map<String, String>>() {});
values.add(valueMap.get("identifier"));
}
break;
}
}
}
return values;
}
private List<ReferenceDepositModel> getReferenceDepositModelOfType(DmpDepositModel dmp, ReferenceType referenceType){
if (dmp.getReferences() == null) return new ArrayList<>();
return dmp.getReferences().stream().filter(x -> x.getType().equals(referenceType)).toList();
}
private void applyZenodoRelator(DmpDepositModel dmp, ZenodoDeposit deposit) throws JsonProcessingException {
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
List<String> acceptedPidTypes = this.pidProperties.getAcceptedTypes();
List<ZenodoRelator> relatedIdentifiers = new ArrayList<>();
for(DescriptionDepositModel descriptionDepositModel: dmp.getDescriptions()){
for(String relatedId: this.identifierProperties.getRelated()){
List<DescriptionFieldDepositModel> fields = findSchematicValues(relatedId, descriptionDepositModel.getFields());
Set<String> values = extractSchematicValues(fields, acceptedPidTypes);
for(String value: values){
ZenodoRelator relator = new ZenodoRelator();
relator.setRelation(relatedId.substring(relatedId.lastIndexOf(".") + 1));
relator.setIdentifier(value);
relatedIdentifiers.add(relator);
}
}
}
deposit.getMetadata().setRelatedIdentifiers(relatedIdentifiers);
}
private void applyAccessRight(DmpDepositModel dmp, ZenodoDeposit deposit){
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
if (dmp.getAccessType() == null) {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
deposit.getMetadata().setAccessConditions("");
} else {
if (dmp.getAccessType().equals(DmpAccessType.Public)) {
Instant publicationDate = dmp.getFinalizedAt();
if (publicationDate == null) publicationDate = Instant.now().minusSeconds(1);
if (publicationDate.isBefore(Instant.now())) {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.OPEN);
} else {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.EMBARGOED);
deposit.getMetadata().setEmbargoDate(publicationDate.toString());
}
} else {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
deposit.getMetadata().setAccessConditions("");
}
}
}
private void applyIsIdenticalTo(DmpDepositModel dmp, ZenodoDeposit deposit, ZenodoProperties zenodoConfig){
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
if (dmp.getAccessType().equals(DmpAccessType.Public)) {
ZenodoRelator relator = new ZenodoRelator();
relator.setIdentifier(zenodoConfig.getDomain() + "/external/zenodo/" + dmp.getId().toString());
relator.setRelation(IS_IDENTICAL_TO);
if (deposit.getMetadata().getRelatedIdentifiers() == null)deposit.getMetadata().setRelatedIdentifiers(new ArrayList<>());
deposit.getMetadata().getRelatedIdentifiers().add(relator);
}
}
private void applyLicenses(DmpDepositModel dmp, ZenodoDeposit deposit){
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
List<ReferenceDepositModel> dmpLicenses = this.getReferenceDepositModelOfType(dmp, ReferenceType.Licenses);
if (dmpLicenses != null && !dmpLicenses.isEmpty()) {
for (ReferenceDepositModel dmpLicense : dmpLicenses) {
String pid = dmpLicense.getDefinition().getFields().stream().filter(x-> PID.equalsIgnoreCase(x.getCode())).map(FieldDepositModel::getValue).findFirst().orElse(null);
if (pid != null && !pid.isBlank()) {
deposit.getMetadata().setLicense(pid);
break;
}
}
}
}
private void applyResearchers(DmpDepositModel dmp, ZenodoDeposit deposit){
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
List<ZenodoContributor> researchers = new ArrayList<>();
List<ReferenceDepositModel> dmpResearchers = this.getReferenceDepositModelOfType(dmp, ReferenceType.Researcher);
if (dmpResearchers != null && !dmpResearchers.isEmpty()) {
for (ReferenceDepositModel researcher : dmpResearchers) {
ZenodoContributor contributor = new ZenodoContributor();
contributor.setName(researcher.getLabel());
contributor.setType(CONTRIBUTOR_TYPE_RESEARCHER);
contributor.setAffiliation(researcher.getSource());
if (researcher.getSource().equalsIgnoreCase(SOURCE_ORCID)) {
contributor.setOrcid(researcher.getReference());
}
researchers.add(contributor);
}
}
if (deposit.getMetadata().getContributors() == null)deposit.getMetadata().setContributors(new ArrayList<>());
deposit.getMetadata().getContributors().addAll(researchers);
}
private void applyGrants(DmpDepositModel dmp, ZenodoDeposit deposit){
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
List<ReferenceDepositModel> dmpGrants = this.getReferenceDepositModelOfType(dmp, ReferenceType.Grants);
List<ReferenceDepositModel> dmpFunders = this.getReferenceDepositModelOfType(dmp, ReferenceType.Funder);
if (dmpGrants != null && !dmpGrants.isEmpty()) {
ReferenceDepositModel depositGrant = dmpGrants.stream().filter(x-> x.getSource().equals(SOURCE_OPENAIRE)).findFirst().orElse(null);
if (depositGrant != null) {
String grantReferenceTail = depositGrant.getReference().split(":")[2];
List<FunderProperties.DoiFunder> doiFunders = this.funderProperties.getAvailable();
if (dmpFunders != null && !dmpFunders.isEmpty()) {
ReferenceDepositModel depositFunder = dmpFunders.get(0);
FunderProperties.DoiFunder doiFunder = doiFunders.stream()
.filter(doiFunder1 -> depositFunder.getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(depositFunder.getLabel()))
.findFirst().orElse(null);
if (doiFunder != null) {
String finalId = doiFunder.getDoi() + "::" + grantReferenceTail;
ZenodoGrant grant = new ZenodoGrant();
grant.setId(finalId);
if (deposit.getMetadata().getGrants() == null)deposit.getMetadata().setGrants(new ArrayList<>());
deposit.getMetadata().getGrants().add(grant);
}
}
}
}
}
private void applyContributors(DmpDepositModel dmp, ZenodoDeposit deposit, ZenodoProperties zenodoConfig){
if (dmp.getUsers() == null) return;
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
List<ReferenceDepositModel> dmpOrganizations = this.getReferenceDepositModelOfType(dmp, ReferenceType.Organizations);
String zenodoAffiliation = zenodoConfig.getAffiliation();
List<ZenodoContributor> contributors = new ArrayList<>();
for (DmpUserDepositModel userDMP: dmp.getUsers()) {
ZenodoContributor contributor = new ZenodoContributor();
contributor.setName(userDMP.getUser().getName());
contributor.setType(CONTRIBUTOR_TYPE_PROJECT_MANAGER);
if (dmpOrganizations != null && !dmpOrganizations.isEmpty()) {
contributor.setAffiliation(dmpOrganizations.stream().map(ReferenceDepositModel::getLabel).collect(Collectors.joining(", ")));
} else {
if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) {
contributor.setAffiliation(zenodoAffiliation);
}
}
contributors.add(contributor);
}
if (deposit.getMetadata().getContributors() == null)deposit.getMetadata().setContributors(new ArrayList<>());
deposit.getMetadata().getContributors().addAll(contributors);
}
private void applyCreators(DmpDepositModel dmp, ZenodoDeposit deposit, ZenodoProperties zenodoConfig){
if (dmp.getUsers() == null) return;
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
List<ReferenceDepositModel> dmpOrganizations = this.getReferenceDepositModelOfType(dmp, ReferenceType.Organizations);
String zenodoAffiliation = zenodoConfig.getAffiliation();
ZenodoCreator creator = new ZenodoCreator();
DmpUserDepositModel dmpDepositModel = dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(DmpUserRole.Owner)).findFirst().orElse(null);
if (dmpDepositModel == null || dmpDepositModel.getUser() == null) return;
creator.setName(dmpDepositModel.getUser().getName());
if (dmpOrganizations != null && !dmpOrganizations.isEmpty()) {
creator.setAffiliation(dmpOrganizations.stream().map(ReferenceDepositModel::getLabel).collect(Collectors.joining(", ")));
} else {
if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) {
creator.setAffiliation(zenodoAffiliation);
}
}
if (deposit.getMetadata().getCreators() == null)deposit.getMetadata().setCreators(new ArrayList<>());
deposit.getMetadata().getCreators().add(creator);
}
}