#8765 - make pids coming from apis as hypelinks in export

This commit is contained in:
Bernaldo Mihasi 2023-06-21 12:00:20 +03:00
parent b6505cda4e
commit 3d367b0589
12 changed files with 324 additions and 60 deletions

View File

@ -1192,7 +1192,7 @@ public class DataManagementPlanManager {
}
public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader, Boolean versioned) throws IOException {
WordBuilder wordBuilder = new WordBuilder(this.environment);
WordBuilder wordBuilder = new WordBuilder(this.environment, configLoader);
VisibilityRuleService visibilityRuleService = new VisibilityRuleServiceImpl();
DatasetWizardModel dataset = new DatasetWizardModel();
XWPFDocument document = configLoader.getDocument();

View File

@ -397,7 +397,7 @@ public class DatasetManager {
}
private XWPFDocument getWordDocument(ConfigLoader configLoader, eu.eudat.data.entities.Dataset datasetEntity, VisibilityRuleService visibilityRuleService, Principal principal) throws IOException {
WordBuilder wordBuilder = new WordBuilder(this.environment);
WordBuilder wordBuilder = new WordBuilder(this.environment, configLoader);
DatasetWizardModel dataset = new DatasetWizardModel();
XWPFDocument document = configLoader.getDatasetDocument();
@ -509,7 +509,7 @@ public class DatasetManager {
}
private XWPFDocument getLightWordDocument(ConfigLoader configLoader, DatasetWizardModel dataset, VisibilityRuleService visibilityRuleService) throws IOException {
WordBuilder wordBuilder = new WordBuilder(this.environment);
WordBuilder wordBuilder = new WordBuilder(this.environment, configLoader);
XWPFDocument document = configLoader.getDocument();
// Space below Dataset title.

View File

@ -3,6 +3,7 @@ package eu.eudat.logic.proxy.config.configloaders;
import eu.eudat.logic.proxy.config.ExternalUrls;
import eu.eudat.logic.proxy.config.Semantic;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders;
import eu.eudat.models.data.pid.PidLinks;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.util.List;
@ -14,5 +15,6 @@ public interface ConfigLoader {
XWPFDocument getDocument();
XWPFDocument getDatasetDocument();
ConfigurableProviders getConfigurableProviders();
PidLinks getPidLinks();
Map<String, String> getKeyToSourceMap();
}

View File

@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.logic.proxy.config.ExternalUrls;
import eu.eudat.logic.proxy.config.Semantic;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders;
import eu.eudat.models.data.pid.PidLinks;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -41,6 +42,7 @@ public class DefaultConfigLoader implements ConfigLoader {
private XWPFDocument document;
private XWPFDocument datasetDocument;
private ConfigurableProviders configurableProviders;
private PidLinks pidLinks;
private Map<String, String> keyToSourceMap;
@Autowired
@ -134,6 +136,25 @@ public class DefaultConfigLoader implements ConfigLoader {
}
}
private void setPidLinks() {
String filePath = environment.getProperty("configuration.pid_links");
logger.info("Loaded also config file: " + filePath);
InputStream is = null;
try {
is = getStreamFromPath(filePath);
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
this.pidLinks = mapper.readValue(is, PidLinks.class);
} catch (IOException | NullPointerException e) {
logger.error(e.getMessage(), e);
} finally {
try {
if (is != null) is.close();
} catch (IOException e) {
logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e);
}
}
}
private void setKeyToSourceMap() {
String filePath = this.environment.getProperty("configuration.externalUrls");
logger.info("Loaded also config file: " + filePath);
@ -192,6 +213,14 @@ public class DefaultConfigLoader implements ConfigLoader {
return configurableProviders;
}
public PidLinks getPidLinks() {
if (pidLinks == null) {
pidLinks = new PidLinks();
this.setPidLinks();
}
return pidLinks;
}
public Map<String, String> getKeyToSourceMap() {
if (keyToSourceMap == null) {
keyToSourceMap = new HashMap<>();

View File

@ -7,11 +7,14 @@ import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.Dataset;
import eu.eudat.data.entities.Organisation;
import eu.eudat.data.entities.Researcher;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.services.forms.VisibilityRuleService;
import eu.eudat.logic.utilities.documents.types.ParagraphStyle;
import eu.eudat.logic.utilities.interfaces.ApplierWithValue;
import eu.eudat.logic.utilities.json.JavaToJson;
import eu.eudat.models.data.components.commons.datafield.*;
import eu.eudat.models.data.pid.PidLink;
import eu.eudat.models.data.pid.PidLinks;
import eu.eudat.models.data.user.components.datasetprofile.Field;
import eu.eudat.models.data.user.components.datasetprofile.FieldSet;
import eu.eudat.models.data.user.components.datasetprofile.Section;
@ -71,8 +74,9 @@ public class WordBuilder {
private Integer indent;
private final ObjectMapper mapper;
private Integer imageCount;
private ConfigLoader configLoader;
public WordBuilder(Environment environment) {
public WordBuilder(Environment environment, ConfigLoader configLoader) {
this.cTAbstractNum = CTAbstractNum.Factory.newInstance();
this.cTAbstractNum.setAbstractNumId(BigInteger.valueOf(1));
this.indent = 0;
@ -80,6 +84,7 @@ public class WordBuilder {
this.mapper = new ObjectMapper();
this.buildOptions(environment);
this.buildOptionsInTable(environment);
this.configLoader = configLoader;
}
private void buildOptionsInTable(Environment environment) {
@ -568,6 +573,37 @@ public class WordBuilder {
return hasValue;
}
private void createHypeLink(XWPFDocument mainDocumentPart, String format, String pidType, String pid, boolean hasMultiplicityItems, boolean isMultiAutoComplete){
PidLink pidLink = this.configLoader.getPidLinks().getPidLinks().stream().filter(pl -> pl.getPid().equals(pidType)).findFirst().orElse(null);
if (pidLink != null) {
if (!hasMultiplicityItems) {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setIndentFromLeft(400 * indent);
if (numId != null) {
paragraph.setNumID(numId);
}
}
if (isMultiAutoComplete) {
XWPFRun r = mainDocumentPart.getLastParagraph().createRun();
r.setText("");
}
XWPFHyperlinkRun run = mainDocumentPart.getLastParagraph().createHyperlinkRun(pidLink.getLink().replace("{pid}", pid));
run.setText(format);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
run.setFontSize(11);
}
else {
String newFormat = (isMultiAutoComplete) ? "" + format : format;
if (hasMultiplicityItems) {
mainDocumentPart.getLastParagraph().createRun().setText(newFormat);
}
else {
addParagraphContent(newFormat, mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
}
}
}
private Boolean createFields(List<Field> fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService, boolean hasMultiplicityItems) {
if (createListing) this.addListing(mainDocumentPart, indent, false, false);
boolean hasValue = false;
@ -607,70 +643,126 @@ public class WordBuilder {
} else if (field.getViewStyle().getRenderStyle().equals("combobox") && field.getData() instanceof AutoCompleteData) {
format = getCommaSeparatedFormatsFromJson(format, "label");
}
boolean isResearcher = field.getViewStyle().getRenderStyle().equals("researchers");
if(format != null && !format.isEmpty()){
Object hasMultiAutoComplete = mapper.convertValue(field.getData(), Map.class).get("multiAutoComplete");
boolean isMultiAutoComplete = hasMultiAutoComplete != null && (boolean)hasMultiAutoComplete;
boolean arrayStringFormat = format.charAt(0) == '[';
if(arrayStringFormat || isMultiAutoComplete){
List<String> values = (arrayStringFormat) ? Arrays.asList(format.substring(1, format.length() - 1).split(",[ ]*")) : Arrays.asList(format.split(",[ ]*"));
if(values.size() > 1) {
boolean orcidResearcher;
for (String val : values) {
orcidResearcher = false;
String orcId = null;
if(isResearcher && val.contains("orcid:")){
orcId = val.substring(val.indexOf(':') + 1, val.indexOf(')'));
val = val.substring(0, val.indexOf(':') + 1) + " ";
orcidResearcher = true;
}
format = "" + val;
switch (field.getViewStyle().getRenderStyle()) {
case "organizations":
case "externalDatasets":
case "publications":
if(format != null && !format.isEmpty()){
Object hasMultiAutoComplete = mapper.convertValue(field.getData(), Map.class).get("multiAutoComplete");
boolean isMultiAutoComplete = hasMultiAutoComplete != null && (boolean)hasMultiAutoComplete;
if(!isMultiAutoComplete){
Map<String, String> value = mapper.readValue((String)field.getValue(), Map.class);
if(hasMultiplicityItems){
mainDocumentPart.getLastParagraph().createRun().setText(format);
if(orcidResearcher){
XWPFHyperlinkRun run = mainDocumentPart.getLastParagraph().createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
mainDocumentPart.getLastParagraph().createRun().setText(")");
}
createHypeLink(mainDocumentPart, format, value.get("pidTypeField"), value.get("pid"), true, false);
hasMultiplicityItems = false;
}
else{
XWPFParagraph paragraph = addParagraphContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
if(orcidResearcher){
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
if (paragraph != null) {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent));
hasValue = true;
createHypeLink(mainDocumentPart, format, value.get("pidTypeField"), value.get("pid"), false, false);
}
}
else{
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
List<Map<String, Object>> values = new ArrayList<>();
try {
values = Arrays.asList(mapper.readValue(field.getValue().toString(), HashMap[].class));
}
catch (Exception e) {
Map <String, Object> map = new HashMap<>();
map.put("label", field.getValue());
values.add(map);
}
if (values.size() > 1) {
for (Map<String, Object> value : values) {
if(hasMultiplicityItems){
createHypeLink(mainDocumentPart, (String) value.get("name"), (String) value.get("pidTypeField"), (String) value.get("pid"), true, true);
hasMultiplicityItems = false;
}
else{
createHypeLink(mainDocumentPart, (String) value.get("name"), (String) value.get("pidTypeField"), (String) value.get("pid"), false, true);
}
}
}
format = null;
else if(values.size() == 1){
if(hasMultiplicityItems){
createHypeLink(mainDocumentPart, format, (String) values.get(0).get("pidTypeField"), (String) values.get(0).get("pid"), true, false);
hasMultiplicityItems = false;
}
else{
createHypeLink(mainDocumentPart, format, (String) values.get(0).get("pidTypeField"), (String) values.get(0).get("pid"), false, false);
}
}
}
hasValue = true;
}
break;
default:
boolean isResearcher = field.getViewStyle().getRenderStyle().equals("researchers");
if(format != null && !format.isEmpty()){
Object hasMultiAutoComplete = mapper.convertValue(field.getData(), Map.class).get("multiAutoComplete");
boolean isMultiAutoComplete = hasMultiAutoComplete != null && (boolean)hasMultiAutoComplete;
boolean arrayStringFormat = format.charAt(0) == '[';
if(arrayStringFormat || isMultiAutoComplete){
List<String> values = (arrayStringFormat) ? Arrays.asList(format.substring(1, format.length() - 1).split(",[ ]*")) : Arrays.asList(format.split(",[ ]*"));
if(values.size() > 1) {
boolean orcidResearcher;
for (String val : values) {
orcidResearcher = false;
String orcId = null;
if(isResearcher && val.contains("orcid:")){
orcId = val.substring(val.indexOf(':') + 1, val.indexOf(')'));
val = val.substring(0, val.indexOf(':') + 1) + " ";
orcidResearcher = true;
}
format = "" + val;
if(hasMultiplicityItems){
mainDocumentPart.getLastParagraph().createRun().setText(format);
if(orcidResearcher){
XWPFHyperlinkRun run = mainDocumentPart.getLastParagraph().createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
mainDocumentPart.getLastParagraph().createRun().setText(")");
}
hasMultiplicityItems = false;
}
else{
XWPFParagraph paragraph = addParagraphContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
if(orcidResearcher){
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
if (paragraph != null) {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent));
hasValue = true;
}
}
format = null;
}
}
else if(values.size() == 1){
format = values.get(0);
}
}
}
else if(values.size() == 1){
format = values.get(0);
if (format != null) {
if (hasMultiplicityItems) {
mainDocumentPart.getLastParagraph().createRun().setText(format);
hasMultiplicityItems = false;
hasValue = true;
}
else {
XWPFParagraph paragraph = addParagraphContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
if (paragraph != null) {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent));
hasValue = true;
}
}
}
}
}
if(hasMultiplicityItems && format != null){
mainDocumentPart.getLastParagraph().createRun().setText(format);
hasMultiplicityItems = false;
hasValue = true;
}
else{
XWPFParagraph paragraph = addParagraphContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
if (paragraph != null) {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent));
hasValue = true;
}
}
}
} catch (IOException e) {
@ -881,7 +973,7 @@ public class WordBuilder {
// logger.info("Reverting to custom parsing");
identifierData = customParse(field.getValue().toString());
}
return "id: " + identifierData.get("identifier") + ", Validation Type: " + identifierData.get("type");
return "id: " + identifierData.get("identifier") + ", Type: " + identifierData.get("type");
}
return "";
}

View File

@ -0,0 +1,21 @@
package eu.eudat.models.data.pid;
public class PidLink {
private String pid;
private String link;
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}

View File

@ -0,0 +1,16 @@
package eu.eudat.models.data.pid;
import java.util.ArrayList;
import java.util.List;
public class PidLinks {
private List<PidLink> pidLinks = new ArrayList<>();
public List<PidLink> getPidLinks() {
return pidLinks;
}
public void setPidLinks(List<PidLink> pidLinks) {
this.pidLinks = pidLinks;
}
}

View File

@ -27,6 +27,7 @@ configuration.semantics=Semantics.json
configuration.h2020template=documents/h2020.docx
configuration.h2020datasettemplate=documents/h2020_dataset.docx
configuration.configurable_login_providers=configurableLoginProviders.json
configuration.pid_links=pidLinks.json
####################EMAIL FILE TEMPLATES OVERRIDES CONFIGURATIONS##########
email.invite=classpath:templates/email/email.html

View File

@ -26,6 +26,7 @@ configuration.externalUrls=externalUrls/ExternalUrls.xml
configuration.h2020template=documents/h2020.docx
configuration.h2020datasettemplate=documents/h2020_dataset.docx
configuration.configurable_login_providers=configurableLoginProviders.json
configuration.pid_links=pidLinks.json
####################EMAIL FILE TEMPLATES OVERRIDES CONFIGURATIONS##########
email.invite=classpath:templates/email/email.html

View File

@ -21,6 +21,7 @@ configuration.h2020template=documents/h2020.docx
configuration.h2020datasettemplate=documents/h2020_dataset.docx
configuration.configurable_login_providers=ConfigurableLoginProviders.json
configuration.doi_funder=DOI_Funder.json
configuration.pid_links=pidLinks.json
####################SPRING MAIL CONFIGURATIONS#################
spring.mail.default-encoding=UTF-8

View File

@ -53,6 +53,7 @@ configuration.semantics=Semantics.json
configuration.h2020template=documents/h2020.docx
configuration.h2020datasettemplate=documents/h2020_dataset.docx
configuration.configurable_login_providers=configurableLoginProviders.json
configuration.pid_links=pidLinks.json
####################EMAIL FILE TEMPLATES OVERRIDES CONFIGURATIONS##########
email.invite=file:templates/email/email.html

View File

@ -0,0 +1,100 @@
{
"pidLinks": [
{
"pid": "doi",
"link": "https://doi.org/{pid}"
},
{
"pid": "uniprot",
"link": "https://uniprot.org/uniprotkb/{pid}"
},
{
"pid": "handle",
"link": "https://hdl.handle.net/{pid}"
},
{
"pid": "arxiv",
"link": "https://arxiv.org/abs/{pid}"
},
{
"pid": "ascl",
"link": "https://ascl.net/{pid}"
},
{
"pid": "orcid",
"link": "https://orcid.org/{pid}"
},
{
"pid": "pmid",
"link": "https://pubmed.ncbi.nlm.nih.gov/{pid}"
},
{
"pid": "ads",
"link": "https://ui.adsabs.harvard.edu/#abs/{pid}"
},
{
"pid": "pmcid",
"link": "https://ncbi.nlm.nih.gov/pmc/{pid}"
},
{
"pid": "gnd",
"link": "https://d-nb.info/gnd/{pid}"
},
{
"pid": "urn",
"link": "https://nbn-resolving.org/{pid}"
},
{
"pid": "sra",
"link": "https://ebi.ac.uk/ena/data/view/{pid}"
},
{
"pid": "bioproject",
"link": "https://ebi.ac.uk/ena/data/view/{pid}"
},
{
"pid": "biosample",
"link": "https://ebi.ac.uk/ena/data/view/{pid}"
},
{
"pid": "ensembl",
"link": "https://ensembl.org/id/{pid}"
},
{
"pid": "refseq",
"link": "https://ncbi.nlm.nih.gov/entrez/viewer.fcgi?val={pid}"
},
{
"pid": "genome",
"link": "https://ncbi.nlm.nih.gov/assembly/{pid}"
},
{
"pid": "geo",
"link": "https://ncbi.nlm.nih.gov/geo/query/acc.cgi?acc={pid}"
},
{
"pid": "arrayexpress_array",
"link": "https://ebi.ac.uk/arrayexpress/arrays/{pid}"
},
{
"pid": "arrayexpress_experiment",
"link": "https://ebi.ac.uk/arrayexpress/experiments/{pid}"
},
{
"pid": "hal",
"link": "https://hal.archives-ouvertes.fr/{pid}"
},
{
"pid": "swh",
"link": "https://archive.softwareheritage.org/{pid}"
},
{
"pid": "ror",
"link": "https://ror.org/{pid}"
},
{
"pid": "viaf",
"link": "https://viaf.org/viaf/{pid}"
}
]
}