Skip to content

Commit 246b5d6

Browse files
authored
Merge pull request #46 from gdcc/RORv2
ROR v2 API support
2 parents 35d7e9d + 13f236f commit 246b5d6

7 files changed

Lines changed: 66 additions & 17 deletions

File tree

examples/affiliation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
Note: This example (.json and .js files) currently rely on the ROR v1 API which won't be supported as of ~12/2025. They could be updated to use v2 of the API as the main authorIdandAffiliationUsingORCIDandROR example and ror.js script have.)
2+
13
The affiliation example illustrates a lookup in ROR.org for the author affiliation field. As with the authors example, it is a simple lookup and fill-in solution. Do not expect changes in the ROR database to be propagated in the Dataset metadata.
24

35
Two files comprise this example:

examples/authorIDandAffilationUsingORCIDandROR.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ This example requires several files:
1414

1515
(These scripts also use jquery and select2 which are already included in Dataverse).
1616

17+
## Dataverse Compatibility note:
18+
19+
The ROR configuration/script now use ROR's v2 API and require Dataverse 6.9+ for full functionality.
20+
For installations on earlier versions, the ROR organization name will not be added to the DataCite XML metadata.
21+
Installations on <= Dataverse v6.8 should not upgrade their CVocConf configuration (keeping the retrieval-url pointed to ROR's v1 API or should delete the contents of the "retrieval-filtering" object (e.g. set "retrieval-filtering": {} ).
22+
23+
## ROR Compatibility note:
24+
As of Dec. 2025, ROR will no longer support it's v1 API. To retain ROR functionality, Dataverse sites should update to use the current ror.js script (which uses ROR's v2 API).
25+
Dataverse instances on v6.9+ should also update to use the current :CVocConf configuration.
26+
Dataverse instances using <=v6.8 also need to update the ror.js script but should not update their configuration (or should delete the contents of the retrieval-filtering object as discussed above).
27+
1728
### How to install:
1829

1930
Minimal:

examples/config/authorsOrcidAndRor.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"term-uri-field": "authorAffiliation",
55
"js-url": ["https://gdcc.github.io/dataverse-external-vocab-support/scripts/ror.js","https://gdcc.github.io/dataverse-external-vocab-support/scripts/cvocutils.js"],
66
"protocol": "ror",
7-
"retrieval-uri": "https://api.ror.org/v1/organizations/{0}",
7+
"retrieval-uri": "https://api.ror.org/v2/organizations/{0}",
88
"allow-free-text": true,
99
"prefix": "https://ror.org/",
1010
"managed-fields": {},
@@ -26,7 +26,7 @@
2626
},
2727
"termName": {
2828
"pattern": "{0}",
29-
"params": ["/name"]
29+
"params": ["/names/types=ror_display/value"]
3030
},
3131
"@type": {
3232
"pattern": "https://schema.org/Organization"

examples/config/demos/rorAuthAffiliation.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"term-uri-field": "authorAffiliation",
55
"js-url": ["/cvoc/js/ror.js","/cvoc/js/cvocutils.js"],
66
"protocol": "ror",
7-
"retrieval-uri": "https://api.ror.org/organizations/{0}",
7+
"retrieval-uri": "https://api.ror.org/v2/organizations/{0}",
88
"allow-free-text": true,
99
"prefix": "https://ror.org/",
1010
"managed-fields": {},
@@ -26,7 +26,7 @@
2626
},
2727
"termName": {
2828
"pattern": "{0}",
29-
"params": ["/name"]
29+
"params": ["/names/types=ror_display/value"]
3030
},
3131
"@type": {
3232
"pattern": "https://schema.org/Organization"

examples/config/grantNumberAgencyRor.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"term-uri-field": "grantNumberAgency",
55
"js-url": ["https://qualitativedatarepository.github.io/dataverse-external-vocab-support/scripts/ror.js","https://qualitativedatarepository.github.io/dataverse-external-vocab-support/scripts/cvocutils.js"],
66
"protocol": "ror",
7-
"retrieval-uri": "https://api.ror.org/organizations/{0}",
7+
"retrieval-uri": "https://api.ror.org/v2/organizations/{0}",
88
"allow-free-text": true,
99
"prefix": "https://ror.org/",
1010
"managed-fields": {},
@@ -26,7 +26,7 @@
2626
},
2727
"termName": {
2828
"pattern": "{0}",
29-
"params": ["/name"]
29+
"params": ["/names/types=ror_display/value"]
3030
},
3131
"@type": {
3232
"pattern": "https://schema.org/Organization"

scripts/affiliation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function createAffiliationModal() {
106106

107107
function affiliationsQuery(str) {
108108
// Vocabulary search REST call
109-
fetch("https://api.ror.org/organizations?query=" + str)
109+
fetch("https://api.ror.org/v1/organizations?query=" + str)
110110
.then(response => response.json())
111111
.then(data => {
112112
let table = document.querySelector('#' + affiliationSearchResultsID + ' tbody');

scripts/ror.js

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
console.log("ror.js..");
22
var rorSelector = "span[data-cvoc-protocol='ror']";
33
var rorInputSelector = "input[data-cvoc-protocol='ror']";
4-
var rorRetrievalUrl = "https://api.ror.org/v1/organizations";
4+
var rorRetrievalUrl = "https://api.ror.org/v2/organizations";
55
var rorIdStem = "https://ror.org/";
66
var rorPrefix = "ror";
77
//Max chars that displays well for a child field
@@ -62,12 +62,19 @@ function expandRors() {
6262
},
6363
success: function(ror, status) {
6464
// If found, construct the HTML for display
65-
var name = ror.name;
66-
var altNames = ror.acronyms;
65+
// Find the display name (type: "ror_display" or "label")
66+
const displayName = ror.names.find(n =>
67+
n.types && (n.types.includes("ror_display") || n.types.includes("label"))
68+
)?.value || ror.id;
69+
70+
// Find all acronyms
71+
const acronyms = ror.names
72+
.filter(n => n.types && n.types.includes("acronym"))
73+
.map(n => n.value);
6774

68-
$(rorElement).html(getRorDisplayHtml(name, rorIdStem + id, altNames, false, true));
75+
$(rorElement).html(getRorDisplayHtml(displayName, rorIdStem + id, acronyms, false, true));
6976
//Store values in localStorage to avoid repeating calls to CrossRef
70-
storeValue(rorPrefix, id, name + "#" + altNames);
77+
storeValue(rorPrefix, id, displayName + "#" + acronyms.join(','));
7178
},
7279
failure: function(jqXHR, textStatus, errorThrown) {
7380
// Generic logging - don't need to do anything if 404 (leave
@@ -190,14 +197,34 @@ function updateRorInputs() {
190197
// Sort the list
191198
// Prioritize active orgs
192199
.sort((a, b) => Number(b.status === 'active') - Number(a.status === 'active'))
200+
// Extract display name and acronyms from the names array
201+
.map(org => {
202+
// Find the display name (type: "ror_display" or "label")
203+
const displayName = org.names.find(n =>
204+
n.types && (n.types.includes("ror_display") || n.types.includes("label"))
205+
)?.value || org.id;
206+
207+
// Find all acronyms
208+
const acronyms = org.names
209+
.filter(n => n.types && n.types.includes("acronym"))
210+
.map(n => n.value);
211+
212+
return {
213+
...org,
214+
name: displayName,
215+
acronyms: acronyms
216+
};
217+
})
193218
// Prioritize those with this acronym
194-
.sort((a, b) => Number(b.acronyms.includes(params.term)) - Number(a.acronyms.includes(params.term)))
219+
.sort((a, b) => Number(b.acronyms.some(acr => acr === params.term)) -
220+
Number(a.acronyms.some(acr => acr === params.term)))
195221
// Prioritize previously used entries
196-
.sort((a, b) => Number(getValue(rorPrefix, b['id'].replace(rorIdStem, '')).name != null) - Number(getValue(rorPrefix, a['id'].replace(rorIdStem, '')).name != null))
222+
.sort((a, b) => Number(getValue(rorPrefix, b['id'].replace(rorIdStem, '')).name != null) -
223+
Number(getValue(rorPrefix, a['id'].replace(rorIdStem, '')).name != null))
197224
.map(
198225
function(x) {
199226
return {
200-
text: x.name + ", " + x.id.replace(rorIdStem, '') + ', ' + x.acronyms,
227+
text: x.name + ", " + x.id.replace(rorIdStem, '') + ', ' + x.acronyms.join(','),
201228
id: x.id
202229
}
203230
})
@@ -236,9 +263,18 @@ function updateRorInputs() {
236263
'Accept': 'application/json'
237264
},
238265
success: function(ror, status) {
239-
var name = ror.name;
266+
// Find the display name (type: "ror_display" or "label")
267+
const displayName = ror.names.find(n =>
268+
n.types && (n.types.includes("ror_display") || n.types.includes("label"))
269+
)?.value || ror.id;
270+
271+
// Find all acronyms
272+
const acronyms = ror.names
273+
.filter(n => n.types && n.types.includes("acronym"))
274+
.map(n => n.value);
275+
240276
//Display the name and id number in the selection menu
241-
var text = name + ", " + ror.id.replace(rorIdStem, '') + ', ' + ror.acronyms;
277+
var text = displayName + ", " + ror.id.replace(rorIdStem, '') + ', ' + acronyms.join(',');
242278
var newOption = new Option(text, id, true, true);
243279
$('#' + selectId).append(newOption).trigger('change');
244280
},

0 commit comments

Comments
 (0)