From e4a9714f464219a947bddf1fa940f9e60e9b04e7 Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Tue, 29 Jun 2021 18:50:29 +0200
Subject: [PATCH 01/10] #7978: linking ORCID from the metadata tab.
---
src/main/webapp/metadataFragment.xhtml | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/src/main/webapp/metadataFragment.xhtml b/src/main/webapp/metadataFragment.xhtml
index 74e1f531234..94760b30abe 100755
--- a/src/main/webapp/metadataFragment.xhtml
+++ b/src/main/webapp/metadataFragment.xhtml
@@ -70,10 +70,25 @@
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
From ce8882c07bc89274fae337aa9dc10fcf8f469dab Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Tue, 13 Jul 2021 22:01:50 +0200
Subject: [PATCH 02/10] #7978: linking ORCID, ISNI, VIAF, ResearcherId and
ScopusID from the metadata tab.
---
.../dataverse/DatasetFieldCompoundValue.java | 68 +++++++++++++++++--
src/main/webapp/metadataFragment.xhtml | 13 +---
2 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
index 407a1d57bd3..3875f16a0c2 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
@@ -14,7 +14,6 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.ResourceBundle;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
@@ -25,7 +24,11 @@
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
+import javax.persistence.Transient;
+
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
/**
*
@@ -68,6 +71,22 @@ public static DatasetFieldCompoundValue createNewEmptyDatasetFieldCompoundValue(
@OrderBy("datasetFieldType ASC")
private List childDatasetFields = new ArrayList<>();
+ private static final Map> linkComponents = Map.of("author", new ImmutablePair<>("authorIdentifierScheme", "authorIdentifier"));
+ @Transient
+ private Map linkMap = new LinkedHashMap<>();
+ @Transient
+ private String linkType = null;
+ @Transient
+ private String linkValue = null;
+ @Transient
+ private Map linkTemplates = Map.of(
+ "ORCID", "https://orcid.org/%s",
+ "ISNI", "https://isni.org/isni/%s",
+ "VIAF", "http://viaf.org/viaf/%s/",
+ "ResearcherID", "https://publons.com/researcher/%s/",
+ "ScopusID", "https://www.scopus.com/authid/detail.uri?authorId=%s"
+ );
+
public Long getId() {
return id;
}
@@ -133,15 +152,29 @@ public DatasetFieldCompoundValue copy(DatasetField parent) {
return compoundValue;
}
- public Map getDisplayValueMap() {
+ public Map getDisplayValueMap() {
// todo - this currently only supports child datasetfields with single values
// need to determine how we would want to handle multiple
Map fieldMap = new LinkedHashMap<>();
+ linkMap = new LinkedHashMap<>();
boolean fixTrailingComma = false;
+ Pair linkComponents = getLinkComponents();
+ linkType = null;
+ linkValue = null;
for (DatasetField childDatasetField : childDatasetFields) {
fixTrailingComma = false;
// skip the value if it is empty or N/A
if (!StringUtils.isBlank(childDatasetField.getValue()) && !DatasetField.NA_VALUE.equals(childDatasetField.getValue())) {
+ if (linkComponents != null) {
+ if (fieldNameEquals(childDatasetField, linkComponents.getKey())) {
+ linkType = childDatasetField.getValue();
+ } else if (fieldNameEquals(childDatasetField, linkComponents.getValue())) {
+ linkValue = childDatasetField.getValue();
+ if (StringUtils.isNotBlank(linkType) && StringUtils.isNotBlank(linkValue))
+ linkMap.put(childDatasetField, true);
+ }
+ }
+
String format = childDatasetField.getDatasetFieldType().getDisplayFormat();
if (StringUtils.isBlank(format)) {
format = "#VALUE";
@@ -161,8 +194,8 @@ public Map getDisplayValueMap() {
//todo: this should be handled in more generic way for any other text that can then be internationalized
// if we need to use replaceAll for regexp, then make sure to use: java.util.regex.Matcher.quoteReplacement()
.replace("#EMAIL", BundleUtil.getStringFromBundle("dataset.email.hiddenMessage"))
- .replace("#VALUE", sanitizedValue );
- fieldMap.put(childDatasetField,displayValue);
+ .replace("#VALUE", sanitizedValue);
+ fieldMap.put(childDatasetField, displayValue);
}
}
@@ -172,7 +205,31 @@ public Map getDisplayValueMap() {
return fieldMap;
}
-
+
+ public String getLink() {
+ if (linkTemplates.containsKey(linkType))
+ return String.format(linkTemplates.get(linkType), linkValue);
+ return null;
+ }
+
+ public boolean isLink(DatasetField datasetField) {
+ return linkMap.containsKey(datasetField) && linkMap.get(datasetField) == true && getLink() != null;
+ }
+
+ private boolean fieldNameEquals(DatasetField datasetField, String linkTypeComponent) {
+ return datasetField.getDatasetFieldType().getName().equals(linkTypeComponent);
+ }
+
+ public boolean isLinkableField() {
+ return linkComponents.containsKey(parentDatasetField.getDatasetFieldType().getName());
+ }
+
+ public Pair getLinkComponents() {
+ if (!isLinkableField())
+ return null;
+ return linkComponents.get(parentDatasetField.getDatasetFieldType().getName());
+ }
+
private Map removeLastComma(Map mapIn) {
Iterator> itr = mapIn.entrySet().iterator();
@@ -192,6 +249,5 @@ private Map removeLastComma(Map mapI
}
return mapIn;
-
}
}
diff --git a/src/main/webapp/metadataFragment.xhtml b/src/main/webapp/metadataFragment.xhtml
index 94760b30abe..4941d334882 100755
--- a/src/main/webapp/metadataFragment.xhtml
+++ b/src/main/webapp/metadataFragment.xhtml
@@ -70,22 +70,15 @@
-
-
-
-
-
-
-
+
+
-
+
From 8b9b5ea51cea6f9880b2009559076c883f24259e Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Wed, 14 Jul 2021 13:19:02 +0200
Subject: [PATCH 03/10] #7978: linking LCNA and GND identifiers from the
metadata tab.
---
.../dataverse/DatasetFieldCompoundValue.java | 33 +++++++++++--------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
index 3875f16a0c2..4707eac25e5 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
@@ -71,21 +71,26 @@ public static DatasetFieldCompoundValue createNewEmptyDatasetFieldCompoundValue(
@OrderBy("datasetFieldType ASC")
private List childDatasetFields = new ArrayList<>();
- private static final Map> linkComponents = Map.of("author", new ImmutablePair<>("authorIdentifierScheme", "authorIdentifier"));
- @Transient
- private Map linkMap = new LinkedHashMap<>();
- @Transient
- private String linkType = null;
- @Transient
- private String linkValue = null;
- @Transient
- private Map linkTemplates = Map.of(
+ // configurations for link creation
+ private static final Map> linkComponents = Map.of(
+ "author", new ImmutablePair<>("authorIdentifierScheme", "authorIdentifier")
+ );
+ private static final Map linkSchemeTemplates = Map.of(
"ORCID", "https://orcid.org/%s",
"ISNI", "https://isni.org/isni/%s",
+ "LCNA", "http://id.loc.gov/authorities/names/%s",
"VIAF", "http://viaf.org/viaf/%s/",
+ "GND", "https://d-nb.info/gnd/%s",
+ // DAI
"ResearcherID", "https://publons.com/researcher/%s/",
"ScopusID", "https://www.scopus.com/authid/detail.uri?authorId=%s"
);
+ @Transient
+ private Map linkMap = new LinkedHashMap<>();
+ @Transient
+ private String linkScheme = null;
+ @Transient
+ private String linkValue = null;
public Long getId() {
return id;
@@ -159,7 +164,7 @@ public Map getDisplayValueMap() {
linkMap = new LinkedHashMap<>();
boolean fixTrailingComma = false;
Pair linkComponents = getLinkComponents();
- linkType = null;
+ linkScheme = null;
linkValue = null;
for (DatasetField childDatasetField : childDatasetFields) {
fixTrailingComma = false;
@@ -167,10 +172,10 @@ public Map getDisplayValueMap() {
if (!StringUtils.isBlank(childDatasetField.getValue()) && !DatasetField.NA_VALUE.equals(childDatasetField.getValue())) {
if (linkComponents != null) {
if (fieldNameEquals(childDatasetField, linkComponents.getKey())) {
- linkType = childDatasetField.getValue();
+ linkScheme = childDatasetField.getValue();
} else if (fieldNameEquals(childDatasetField, linkComponents.getValue())) {
linkValue = childDatasetField.getValue();
- if (StringUtils.isNotBlank(linkType) && StringUtils.isNotBlank(linkValue))
+ if (StringUtils.isNotBlank(linkScheme) && StringUtils.isNotBlank(linkValue))
linkMap.put(childDatasetField, true);
}
}
@@ -207,8 +212,8 @@ public Map getDisplayValueMap() {
}
public String getLink() {
- if (linkTemplates.containsKey(linkType))
- return String.format(linkTemplates.get(linkType), linkValue);
+ if (linkSchemeTemplates.containsKey(linkScheme))
+ return String.format(linkSchemeTemplates.get(linkScheme), linkValue);
return null;
}
From 4d4167a121d4806f4fb2d23ff066a124cd9af8fb Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Wed, 14 Jul 2021 13:41:56 +0200
Subject: [PATCH 04/10] #7978: linking LCNA and GND identifiers from the
metadata tab.
---
.../edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
index 4707eac25e5..4505d99c0f4 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
@@ -85,6 +85,8 @@ public static DatasetFieldCompoundValue createNewEmptyDatasetFieldCompoundValue(
"ResearcherID", "https://publons.com/researcher/%s/",
"ScopusID", "https://www.scopus.com/authid/detail.uri?authorId=%s"
);
+
+ // field for handling links. Annotation '@Transient' prevents these fields to be saved in DB
@Transient
private Map linkMap = new LinkedHashMap<>();
@Transient
From 3dbd1d37f7c0122b4aacf3130a0fe294c9210367 Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Tue, 24 Aug 2021 16:40:33 +0200
Subject: [PATCH 05/10] #7978: Modifying DatasetAuthor - creating a map for the
identifier regex pattern and the link pattern.
---
.../harvard/iq/dataverse/DatasetAuthor.java | 74 ++++++++-----------
.../dataverse/DatasetFieldCompoundValue.java | 14 +---
.../harvard/iq/dataverse/LinkTemplate.java | 21 ++++++
.../iq/dataverse/DatasetAuthorTest.java | 4 +-
.../DatasetFieldValueValidatorTest.java | 10 +--
5 files changed, 62 insertions(+), 61 deletions(-)
create mode 100644 src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java b/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
index ce8405a0164..0cb41eb510b 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
@@ -7,14 +7,13 @@
package edu.harvard.iq.dataverse;
import java.util.Comparator;
+import java.util.Map;
import java.util.regex.Pattern;
-
/**
*
* @author skraffmiller
*/
-
public class DatasetAuthor {
public static Comparator DisplayOrder = new Comparator(){
@@ -89,17 +88,25 @@ public boolean isEmpty() {
);
}
- /**
- * https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier
- */
- final public static String REGEX_ORCID = "^\\d{4}-\\d{4}-\\d{4}-(\\d{4}|\\d{3}X)$";
- final public static String REGEX_ISNI = "^\\d*$";
- final public static String REGEX_LCNA = "^[a-z]+\\d+$";
- final public static String REGEX_VIAF = "^\\d*$";
- /**
- * GND regex from https://www.wikidata.org/wiki/Property:P227
- */
- final public static String REGEX_GND = "^1[01]?\\d{7}[0-9X]|[47]\\d{6}-\\d|[1-9]\\d{0,7}-[0-9X]|3\\d{7}[0-9X]$";
+ public static final Map linkSchemeTemplates = Map.of(
+ // https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier
+ "ORCID",
+ new LinkTemplate("https://orcid.org/%s", "^\\d{4}-\\d{4}-\\d{4}-(\\d{4}|\\d{3}X)$"),
+ "ISNI",
+ new LinkTemplate("http://www.isni.org/isni/%s", "^\\d*$"),
+ "LCNA",
+ new LinkTemplate("http://id.loc.gov/authorities/names/%s", "^[a-z]+\\d+$"),
+ "VIAF",
+ new LinkTemplate("https://viaf.org/viaf/%s", "^\\d*$"),
+ // GND regex from https://www.wikidata.org/wiki/Property:P227
+ "GND",
+ new LinkTemplate("https://d-nb.info/gnd/%s", "^1[01]?\\d{7}[0-9X]|[47]\\d{6}-\\d|[1-9]\\d{0,7}-[0-9X]|3\\d{7}[0-9X]$"),
+ // DAI is missing from this list
+ "ResearcherID",
+ new LinkTemplate("https://publons.com/researcher/%s/", "^[A-Z\\d][A-Z\\d-]+[A-Z\\d]$"),
+ "ScopusID",
+ new LinkTemplate("https://www.scopus.com/authid/detail.uri?authorId=%s", "^\\d*$")
+ );
/**
* Each author identification type has its own valid pattern/syntax.
@@ -109,39 +116,22 @@ public static Pattern getValidPattern(String regex) {
}
public String getIdentifierAsUrl() {
+ if (idType != null && !idType.isEmpty() && idValue != null && !idValue.isEmpty()) {
+ return getIdentifierAsUrl(idType, idValue);
+ }
+ return null;
+ }
+
+ public static String getIdentifierAsUrl(String idType, String idValue) {
if (idType != null && !idType.isEmpty() && idValue != null && !idValue.isEmpty()) {
DatasetFieldValueValidator datasetFieldValueValidator = new DatasetFieldValueValidator();
- switch (idType) {
- case "ORCID":
- if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, getValidPattern(REGEX_ORCID))) {
- return "https://orcid.org/" + idValue;
- }
- break;
- case "ISNI":
- if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, getValidPattern(REGEX_ISNI))) {
- return "http://www.isni.org/isni/" + idValue;
- }
- break;
- case "LCNA":
- if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, getValidPattern(REGEX_LCNA))) {
- return "http://id.loc.gov/authorities/names/" + idValue;
- }
- break;
- case "VIAF":
- if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, getValidPattern(REGEX_VIAF))) {
- return "https://viaf.org/viaf/" + idValue;
- }
- break;
- case "GND":
- if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, getValidPattern(REGEX_GND))) {
- return "https://d-nb.info/gnd/" + idValue;
- }
- break;
- default:
- break;
+ if (linkSchemeTemplates.containsKey(idType)) {
+ LinkTemplate template = linkSchemeTemplates.get(idType);
+ if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, template.getPattern())) {
+ return String.format(template.getTemplate(), idValue);
+ }
}
}
return null;
}
-
}
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
index 4505d99c0f4..72a5fe15b9a 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
@@ -75,16 +75,6 @@ public static DatasetFieldCompoundValue createNewEmptyDatasetFieldCompoundValue(
private static final Map> linkComponents = Map.of(
"author", new ImmutablePair<>("authorIdentifierScheme", "authorIdentifier")
);
- private static final Map linkSchemeTemplates = Map.of(
- "ORCID", "https://orcid.org/%s",
- "ISNI", "https://isni.org/isni/%s",
- "LCNA", "http://id.loc.gov/authorities/names/%s",
- "VIAF", "http://viaf.org/viaf/%s/",
- "GND", "https://d-nb.info/gnd/%s",
- // DAI
- "ResearcherID", "https://publons.com/researcher/%s/",
- "ScopusID", "https://www.scopus.com/authid/detail.uri?authorId=%s"
- );
// field for handling links. Annotation '@Transient' prevents these fields to be saved in DB
@Transient
@@ -214,9 +204,7 @@ public Map getDisplayValueMap() {
}
public String getLink() {
- if (linkSchemeTemplates.containsKey(linkScheme))
- return String.format(linkSchemeTemplates.get(linkScheme), linkValue);
- return null;
+ return DatasetAuthor.getIdentifierAsUrl(linkScheme, linkValue);
}
public boolean isLink(DatasetField datasetField) {
diff --git a/src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java b/src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java
new file mode 100644
index 00000000000..6f9ff2a58fe
--- /dev/null
+++ b/src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java
@@ -0,0 +1,21 @@
+package edu.harvard.iq.dataverse;
+
+import java.util.regex.Pattern;
+
+public class LinkTemplate {
+ private String template;
+ private Pattern pattern;
+
+ public LinkTemplate(String template, String regex) {
+ this.template = template;
+ this.pattern = Pattern.compile(regex);
+ }
+
+ public String getTemplate() {
+ return template;
+ }
+
+ public Pattern getPattern() {
+ return pattern;
+ }
+}
diff --git a/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java b/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java
index 5b943448fca..0d349ee6824 100644
--- a/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java
+++ b/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java
@@ -31,6 +31,9 @@ public static Collection parameters() {
{ "LCNA", "n82058243", "http://id.loc.gov/authorities/names/n82058243" },
{ "VIAF", "172389567", "https://viaf.org/viaf/172389567" },
{ "GND", "4079154-3", "https://d-nb.info/gnd/4079154-3" },
+ { "ResearcherID", "4079154", "https://publons.com/researcher/4079154/" },
+ { "ResearcherID", "AAW-9289-2021", "https://publons.com/researcher/AAW-9289-2021/" },
+ { "ScopusID", "4079154", "https://www.scopus.com/authid/detail.uri?authorId=4079154" },
{ null, null, null, },
});
}
@@ -44,5 +47,4 @@ public void getIdentifierAsUrl() {
}
assertEquals(expectedIdentifierAsUrl, datasetAuthor.getIdentifierAsUrl());
}
-
}
diff --git a/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java b/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java
index dedafe7722e..d11d5ca747b 100644
--- a/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java
+++ b/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java
@@ -141,7 +141,7 @@ public void testIsValid() {
@Test
public void testIsValidAuthorIdentifierOrcid() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.getValidPattern(DatasetAuthor.REGEX_ORCID);
+ Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("ORCID").getPattern();
assertTrue(validator.isValidAuthorIdentifier("0000-0002-1825-0097", pattern));
// An "X" at the end of an ORCID is less common but still valid.
assertTrue(validator.isValidAuthorIdentifier("0000-0002-1694-233X", pattern));
@@ -154,7 +154,7 @@ public void testIsValidAuthorIdentifierOrcid() {
@Test
public void testIsValidAuthorIdentifierIsni() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.getValidPattern(DatasetAuthor.REGEX_ISNI);
+ Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("ISNI").getPattern();
assertTrue(validator.isValidAuthorIdentifier("0000000121032683", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
}
@@ -162,7 +162,7 @@ public void testIsValidAuthorIdentifierIsni() {
@Test
public void testIsValidAuthorIdentifierLcna() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.getValidPattern(DatasetAuthor.REGEX_LCNA);
+ Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("LCNA").getPattern();
assertTrue(validator.isValidAuthorIdentifier("n82058243", pattern));
assertTrue(validator.isValidAuthorIdentifier("foobar123", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
@@ -171,7 +171,7 @@ public void testIsValidAuthorIdentifierLcna() {
@Test
public void testIsValidAuthorIdentifierViaf() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.getValidPattern(DatasetAuthor.REGEX_VIAF);
+ Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("VIAF").getPattern();
assertTrue(validator.isValidAuthorIdentifier("172389567", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
}
@@ -179,7 +179,7 @@ public void testIsValidAuthorIdentifierViaf() {
@Test
public void testIsValidAuthorIdentifierGnd() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.getValidPattern(DatasetAuthor.REGEX_GND);
+ Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("GND").getPattern();
assertTrue(validator.isValidAuthorIdentifier("4079154-3", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
}
From ec466d890bd3a7b5d78209719cbec9077d1be656 Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Wed, 25 Aug 2021 10:34:40 +0200
Subject: [PATCH 06/10] #7978: adding a release note.
---
.../7978-linking-ORCID-profile-from-metadata-tab.md | 3 +++
src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
create mode 100644 doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
diff --git a/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md b/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
new file mode 100644
index 00000000000..92eea36eea3
--- /dev/null
+++ b/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
@@ -0,0 +1,3 @@
+### Displaying author's identifier as link
+
+In the dataset page's metadatatab the author's identifier is displayed as a clickable link, which points to the profile page in the external service (ORCID, VIAF etc.), given that the identifier scheme provides a resolvable landing page.
\ No newline at end of file
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java b/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
index 0cb41eb510b..28d2a12141d 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
@@ -101,7 +101,7 @@ public boolean isEmpty() {
// GND regex from https://www.wikidata.org/wiki/Property:P227
"GND",
new LinkTemplate("https://d-nb.info/gnd/%s", "^1[01]?\\d{7}[0-9X]|[47]\\d{6}-\\d|[1-9]\\d{0,7}-[0-9X]|3\\d{7}[0-9X]$"),
- // DAI is missing from this list
+ // note: DAI is missing from this list, because it doesn't have resolvable URL
"ResearcherID",
new LinkTemplate("https://publons.com/researcher/%s/", "^[A-Z\\d][A-Z\\d-]+[A-Z\\d]$"),
"ScopusID",
From a8c14451b34bb2fbb98a605d69a47931b94d482e Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Wed, 25 Aug 2021 15:06:52 +0200
Subject: [PATCH 07/10] #7978: adding test parameters.
---
.../java/edu/harvard/iq/dataverse/DatasetAuthorTest.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java b/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java
index 0d349ee6824..fddb95eda9e 100644
--- a/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java
+++ b/src/test/java/edu/harvard/iq/dataverse/DatasetAuthorTest.java
@@ -31,9 +31,10 @@ public static Collection parameters() {
{ "LCNA", "n82058243", "http://id.loc.gov/authorities/names/n82058243" },
{ "VIAF", "172389567", "https://viaf.org/viaf/172389567" },
{ "GND", "4079154-3", "https://d-nb.info/gnd/4079154-3" },
- { "ResearcherID", "4079154", "https://publons.com/researcher/4079154/" },
+ { "ResearcherID", "634082", "https://publons.com/researcher/634082/" },
{ "ResearcherID", "AAW-9289-2021", "https://publons.com/researcher/AAW-9289-2021/" },
- { "ScopusID", "4079154", "https://www.scopus.com/authid/detail.uri?authorId=4079154" },
+ { "ResearcherID", "J-9733-2013", "https://publons.com/researcher/J-9733-2013/" },
+ { "ScopusID", "6602344670", "https://www.scopus.com/authid/detail.uri?authorId=6602344670" },
{ null, null, null, },
});
}
From 6e571a159a68abadd2f4dbd2311780908475e477 Mon Sep 17 00:00:00 2001
From: Philip Durbin
Date: Wed, 25 Aug 2021 09:52:53 -0400
Subject: [PATCH 08/10] typo #7978
---
.../7978-linking-ORCID-profile-from-metadata-tab.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md b/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
index 92eea36eea3..f19c5dd696b 100644
--- a/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
+++ b/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
@@ -1,3 +1,3 @@
### Displaying author's identifier as link
-In the dataset page's metadatatab the author's identifier is displayed as a clickable link, which points to the profile page in the external service (ORCID, VIAF etc.), given that the identifier scheme provides a resolvable landing page.
\ No newline at end of file
+In the dataset page's metadata tab the author's identifier is displayed as a clickable link, which points to the profile page in the external service (ORCID, VIAF etc.), given that the identifier scheme provides a resolvable landing page.
From 2af4252c228f110fc18d7fcb51b2c035e1175c9e Mon Sep 17 00:00:00 2001
From: pkiraly
Date: Fri, 8 Oct 2021 13:26:33 +0200
Subject: [PATCH 09/10] #7978: fixing conflicts and refactoring the solution
making an enumeration of linked external identifier services.
---
.../harvard/iq/dataverse/DatasetAuthor.java | 41 ++-----------
.../dataverse/DatasetFieldCompoundValue.java | 2 +-
.../iq/dataverse/ExternalIdentifier.java | 58 +++++++++++++++++++
.../harvard/iq/dataverse/LinkTemplate.java | 21 -------
src/main/webapp/metadataFragment.xhtml | 16 +++--
.../DatasetFieldValueValidatorTest.java | 10 ++--
.../iq/dataverse/ExternalIdentifierTest.java | 53 +++++++++++++++++
7 files changed, 130 insertions(+), 71 deletions(-)
create mode 100644 src/main/java/edu/harvard/iq/dataverse/ExternalIdentifier.java
delete mode 100644 src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java
create mode 100644 src/test/java/edu/harvard/iq/dataverse/ExternalIdentifierTest.java
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java b/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
index 28d2a12141d..d33d709107f 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetAuthor.java
@@ -7,8 +7,6 @@
package edu.harvard.iq.dataverse;
import java.util.Comparator;
-import java.util.Map;
-import java.util.regex.Pattern;
/**
*
@@ -88,33 +86,6 @@ public boolean isEmpty() {
);
}
- public static final Map linkSchemeTemplates = Map.of(
- // https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier
- "ORCID",
- new LinkTemplate("https://orcid.org/%s", "^\\d{4}-\\d{4}-\\d{4}-(\\d{4}|\\d{3}X)$"),
- "ISNI",
- new LinkTemplate("http://www.isni.org/isni/%s", "^\\d*$"),
- "LCNA",
- new LinkTemplate("http://id.loc.gov/authorities/names/%s", "^[a-z]+\\d+$"),
- "VIAF",
- new LinkTemplate("https://viaf.org/viaf/%s", "^\\d*$"),
- // GND regex from https://www.wikidata.org/wiki/Property:P227
- "GND",
- new LinkTemplate("https://d-nb.info/gnd/%s", "^1[01]?\\d{7}[0-9X]|[47]\\d{6}-\\d|[1-9]\\d{0,7}-[0-9X]|3\\d{7}[0-9X]$"),
- // note: DAI is missing from this list, because it doesn't have resolvable URL
- "ResearcherID",
- new LinkTemplate("https://publons.com/researcher/%s/", "^[A-Z\\d][A-Z\\d-]+[A-Z\\d]$"),
- "ScopusID",
- new LinkTemplate("https://www.scopus.com/authid/detail.uri?authorId=%s", "^\\d*$")
- );
-
- /**
- * Each author identification type has its own valid pattern/syntax.
- */
- public static Pattern getValidPattern(String regex) {
- return Pattern.compile(regex);
- }
-
public String getIdentifierAsUrl() {
if (idType != null && !idType.isEmpty() && idValue != null && !idValue.isEmpty()) {
return getIdentifierAsUrl(idType, idValue);
@@ -124,12 +95,12 @@ public String getIdentifierAsUrl() {
public static String getIdentifierAsUrl(String idType, String idValue) {
if (idType != null && !idType.isEmpty() && idValue != null && !idValue.isEmpty()) {
- DatasetFieldValueValidator datasetFieldValueValidator = new DatasetFieldValueValidator();
- if (linkSchemeTemplates.containsKey(idType)) {
- LinkTemplate template = linkSchemeTemplates.get(idType);
- if (datasetFieldValueValidator.isValidAuthorIdentifier(idValue, template.getPattern())) {
- return String.format(template.getTemplate(), idValue);
- }
+ try {
+ ExternalIdentifier externalIdentifier = ExternalIdentifier.valueOf(idType);
+ if (externalIdentifier.isValidIdentifier(idValue))
+ return externalIdentifier.format(idValue);
+ } catch (Exception e) {
+ // non registered identifier
}
}
return null;
diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
index 72a5fe15b9a..5d83f1e4f8d 100644
--- a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
+++ b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldCompoundValue.java
@@ -153,7 +153,7 @@ public Map getDisplayValueMap() {
// todo - this currently only supports child datasetfields with single values
// need to determine how we would want to handle multiple
Map fieldMap = new LinkedHashMap<>();
- linkMap = new LinkedHashMap<>();
+ linkMap.clear();
boolean fixTrailingComma = false;
Pair linkComponents = getLinkComponents();
linkScheme = null;
diff --git a/src/main/java/edu/harvard/iq/dataverse/ExternalIdentifier.java b/src/main/java/edu/harvard/iq/dataverse/ExternalIdentifier.java
new file mode 100644
index 00000000000..0b7285c017e
--- /dev/null
+++ b/src/main/java/edu/harvard/iq/dataverse/ExternalIdentifier.java
@@ -0,0 +1,58 @@
+package edu.harvard.iq.dataverse;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public enum ExternalIdentifier {
+ ORCID("ORCID", "https://orcid.org/%s", "^\\d{4}-\\d{4}-\\d{4}-(\\d{4}|\\d{3}X)$"),
+ ISNI("ISNI", "http://www.isni.org/isni/%s", "^\\d*$"),
+ LCNA("LCNA", "http://id.loc.gov/authorities/names/%s", "^[a-z]+\\d+$"),
+ VIAF("VIAF", "https://viaf.org/viaf/%s", "^\\d*$"),
+ // GND regex from https://www.wikidata.org/wiki/Property:P227
+ GND("GND", "https://d-nb.info/gnd/%s", "^1[01]?\\d{7}[0-9X]|[47]\\d{6}-\\d|[1-9]\\d{0,7}-[0-9X]|3\\d{7}[0-9X]$"),
+ // note: DAI is missing from this list, because it doesn't have resolvable URL
+ ResearcherID("ResearcherID", "https://publons.com/researcher/%s/", "^[A-Z\\d][A-Z\\d-]+[A-Z\\d]$"),
+ ScopusID("ScopusID", "https://www.scopus.com/authid/detail.uri?authorId=%s", "^\\d*$");
+
+ private String name;
+ private String template;
+ private Pattern pattern;
+ private Matcher matcher;
+
+ ExternalIdentifier(String name, String template, String regex) {
+ this.template = template;
+ this.pattern = Pattern.compile(regex);
+ this.matcher = pattern.matcher("");
+ }
+
+ public ExternalIdentifier of(String name) {
+ System.err.println(name);
+ for (ExternalIdentifier identifier : values()) {
+ System.err.println(" vs " + identifier.name);
+ if (identifier.name.toLowerCase().equals(name.toLowerCase())) {
+ return identifier;
+ }
+ }
+ return null;
+ }
+
+ public boolean isValidIdentifier(String userInput) {
+ return matcher.reset(userInput).matches();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTemplate() {
+ return template;
+ }
+
+ public Pattern getPattern() {
+ return pattern;
+ }
+
+ public String format(String idValue) {
+ return String.format(template, idValue);
+ }
+}
diff --git a/src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java b/src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java
deleted file mode 100644
index 6f9ff2a58fe..00000000000
--- a/src/main/java/edu/harvard/iq/dataverse/LinkTemplate.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package edu.harvard.iq.dataverse;
-
-import java.util.regex.Pattern;
-
-public class LinkTemplate {
- private String template;
- private Pattern pattern;
-
- public LinkTemplate(String template, String regex) {
- this.template = template;
- this.pattern = Pattern.compile(regex);
- }
-
- public String getTemplate() {
- return template;
- }
-
- public Pattern getPattern() {
- return pattern;
- }
-}
diff --git a/src/main/webapp/metadataFragment.xhtml b/src/main/webapp/metadataFragment.xhtml
index 0fcda310687..f1b99e9f366 100755
--- a/src/main/webapp/metadataFragment.xhtml
+++ b/src/main/webapp/metadataFragment.xhtml
@@ -64,7 +64,7 @@
-
+ |
-
+
-
-
-
+
+
+
|
-
+ |
- |
+
diff --git a/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java b/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java
index d11d5ca747b..804b573c7b7 100644
--- a/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java
+++ b/src/test/java/edu/harvard/iq/dataverse/DatasetFieldValueValidatorTest.java
@@ -141,7 +141,7 @@ public void testIsValid() {
@Test
public void testIsValidAuthorIdentifierOrcid() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("ORCID").getPattern();
+ Pattern pattern = ExternalIdentifier.valueOf("ORCID").getPattern();
assertTrue(validator.isValidAuthorIdentifier("0000-0002-1825-0097", pattern));
// An "X" at the end of an ORCID is less common but still valid.
assertTrue(validator.isValidAuthorIdentifier("0000-0002-1694-233X", pattern));
@@ -154,7 +154,7 @@ public void testIsValidAuthorIdentifierOrcid() {
@Test
public void testIsValidAuthorIdentifierIsni() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("ISNI").getPattern();
+ Pattern pattern = ExternalIdentifier.valueOf("ISNI").getPattern();
assertTrue(validator.isValidAuthorIdentifier("0000000121032683", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
}
@@ -162,7 +162,7 @@ public void testIsValidAuthorIdentifierIsni() {
@Test
public void testIsValidAuthorIdentifierLcna() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("LCNA").getPattern();
+ Pattern pattern = ExternalIdentifier.valueOf("LCNA").getPattern();
assertTrue(validator.isValidAuthorIdentifier("n82058243", pattern));
assertTrue(validator.isValidAuthorIdentifier("foobar123", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
@@ -171,7 +171,7 @@ public void testIsValidAuthorIdentifierLcna() {
@Test
public void testIsValidAuthorIdentifierViaf() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("VIAF").getPattern();
+ Pattern pattern = ExternalIdentifier.valueOf("VIAF").getPattern();
assertTrue(validator.isValidAuthorIdentifier("172389567", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
}
@@ -179,7 +179,7 @@ public void testIsValidAuthorIdentifierViaf() {
@Test
public void testIsValidAuthorIdentifierGnd() {
DatasetFieldValueValidator validator = new DatasetFieldValueValidator();
- Pattern pattern = DatasetAuthor.linkSchemeTemplates.get("GND").getPattern();
+ Pattern pattern = ExternalIdentifier.valueOf("GND").getPattern();
assertTrue(validator.isValidAuthorIdentifier("4079154-3", pattern));
assertFalse(validator.isValidAuthorIdentifier("junk", pattern));
}
diff --git a/src/test/java/edu/harvard/iq/dataverse/ExternalIdentifierTest.java b/src/test/java/edu/harvard/iq/dataverse/ExternalIdentifierTest.java
new file mode 100644
index 00000000000..c14d2e4086e
--- /dev/null
+++ b/src/test/java/edu/harvard/iq/dataverse/ExternalIdentifierTest.java
@@ -0,0 +1,53 @@
+package edu.harvard.iq.dataverse;
+
+import org.junit.Test;
+
+import java.util.regex.Pattern;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ExternalIdentifierTest {
+
+ @Test
+ public void testIsValidAuthorIdentifierOrcid() {
+ ExternalIdentifier identifier = ExternalIdentifier.valueOf("ORCID");
+ assertTrue(identifier.isValidIdentifier("0000-0002-1825-0097"));
+ // An "X" at the end of an ORCID is less common but still valid.
+ assertTrue(identifier.isValidIdentifier("0000-0002-1694-233X"));
+ assertFalse(identifier.isValidIdentifier("0000 0002 1825 0097"));
+ assertFalse(identifier.isValidIdentifier(" 0000-0002-1825-0097"));
+ assertFalse(identifier.isValidIdentifier("0000-0002-1825-0097 "));
+ assertFalse(identifier.isValidIdentifier("junk"));
+ }
+
+ @Test
+ public void testIsValidAuthorIdentifierIsni() {
+ ExternalIdentifier identifier = ExternalIdentifier.valueOf("ISNI");
+ assertTrue(identifier.isValidIdentifier("0000000121032683"));
+ assertFalse(identifier.isValidIdentifier("junk"));
+ }
+
+ @Test
+ public void testIsValidAuthorIdentifierLcna() {
+ ExternalIdentifier identifier = ExternalIdentifier.valueOf("LCNA");
+ assertTrue(identifier.isValidIdentifier("n82058243"));
+ assertTrue(identifier.isValidIdentifier("foobar123"));
+ assertFalse(identifier.isValidIdentifier("junk"));
+ }
+
+ @Test
+ public void testIsValidAuthorIdentifierViaf() {
+ ExternalIdentifier identifier = ExternalIdentifier.valueOf("VIAF");
+ assertTrue(identifier.isValidIdentifier("172389567"));
+ assertFalse(identifier.isValidIdentifier("junk"));
+ }
+
+ @Test
+ public void testIsValidAuthorIdentifierGnd() {
+ ExternalIdentifier identifier = ExternalIdentifier.valueOf("GND");
+ assertTrue(identifier.isValidIdentifier("4079154-3"));
+ assertFalse(identifier.isValidIdentifier("junk"));
+ }
+
+}
From 1e66657ed8d2f1b23d493bd58acb6b905a854f4e Mon Sep 17 00:00:00 2001
From: Philip Durbin
Date: Wed, 17 Nov 2021 11:41:44 -0500
Subject: [PATCH 10/10] mention no link if identifier is not valid #7978
---
.../7978-linking-ORCID-profile-from-metadata-tab.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md b/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
index f19c5dd696b..62c8b308073 100644
--- a/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
+++ b/doc/release-notes/7978-linking-ORCID-profile-from-metadata-tab.md
@@ -1,3 +1,3 @@
### Displaying author's identifier as link
-In the dataset page's metadata tab the author's identifier is displayed as a clickable link, which points to the profile page in the external service (ORCID, VIAF etc.), given that the identifier scheme provides a resolvable landing page.
+In the dataset page's metadata tab the author's identifier is displayed as a clickable link, which points to the profile page in the external service (ORCID, VIAF etc.), given that the identifier scheme provides a resolvable landing page. If the identifier does not match the expected scheme, a link is not shown.