Skip to content

Commit

Permalink
Merge pull request IQSS#10806 from IQSS/8581-crossref-provider2
Browse files Browse the repository at this point in the history
Crossref as a DOI provider (experimental)
  • Loading branch information
pdurbin authored Sep 17, 2024
2 parents c9ec859 + 8dfd5f3 commit ec882e3
Show file tree
Hide file tree
Showing 9 changed files with 703 additions and 5 deletions.
3 changes: 3 additions & 0 deletions doc/release-notes/8581-add-crossref-pid-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added CrossRef DOI Pid Provider

See Installation Configuration document for JVM Settings to enable CrossRef as a Pid Provider
35 changes: 35 additions & 0 deletions doc/sphinx-guides/source/installation/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,41 @@ for `Fabrica <https://doi.datacite.org/>`_ and their APIs. You need to provide
the same credentials (``username``, ``password``) to Dataverse software to mint and manage DOIs for you.
As noted above, you should use one of the more secure options for setting the password.

CrossRef-specific Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^

dataverse.pid.*.crossref.url
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dataverse.pid.*.crossref.rest-api-url
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dataverse.pid.*.crossref.username
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dataverse.pid.*.crossref.password
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dataverse.pid.*.crossref.depositor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dataverse.pid.*.crossref.depositor-email
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

CrossRef is an experimental provider.
PID Providers of type ``crossref`` require six additional parameters that define how the provider connects to CrossRef.
CrossRef has two APIs that are used in Dataverse:

The base URL of the `CrossRef <https://api.crossref.org>`_,
used to mint and manage DOIs. Current valid values for ``dataverse.pid.*.crossref.url`` are "https://doi.crossref.org" and ``dataverse.pid.*.crossref.rest-api-url`` are "https://api.crossref.org" (production).
``dataverse.pid.*.crossref.username=crusername``
``dataverse.pid.*.crossref.password=secret``
``dataverse.pid.*.crossref.depositor=xyz``
``dataverse.pid.*.crossref.depositor-email=xyz@example.com``

CrossRef uses `HTTP Basic authentication <https://en.wikipedia.org/wiki/Basic_access_authentication>`_
XML files can be POSTed to CrossRef where they are added to the submission queue to await processing
`Post URL <https://doi.crossref.org/>`_
REST API allows the search and reuse our members' metadata.
`Rest API <https://api.crossref.org/>`_ and their APIs.
You need to provide the same credentials (``username``, ``password``) to Dataverse software to mint and manage DOIs for you.
As noted above, you should use one of the more secure options for setting the password.
Depositor and Depositor Email are used for the generation and distribution of Depositor reports.

.. _dataverse.pid.*.ezid:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package edu.harvard.iq.dataverse.pidproviders.doi.crossref;

import edu.harvard.iq.dataverse.DvObject;
import edu.harvard.iq.dataverse.GlobalId;
import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class CrossRefDOIProvider extends AbstractDOIProvider {
private static final Logger logger = Logger.getLogger(CrossRefDOIProvider.class.getCanonicalName());

public static final String TYPE = "crossref";

CrossRefDOIRegisterService crossRefDOIRegisterService;

public CrossRefDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList,
String url, String apiUrl, String username, String password, String depositor, String depositorEmail) {
super(id, label, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat,
managedList, excludedList);

crossRefDOIRegisterService = new CrossRefDOIRegisterService(url, apiUrl, username, password, depositor, depositorEmail);
}

@Override
public boolean alreadyRegistered(GlobalId pid, boolean noProviderDefault) throws Exception {
logger.info("CrossRef alreadyRegistered");
if (pid == null || pid.asString().isEmpty()) {
logger.fine("No identifier sent.");
return false;
}
boolean alreadyExists;
String identifier = pid.asString();
try {
alreadyExists = crossRefDOIRegisterService.testDOIExists(identifier);
} catch (Exception e) {
logger.log(Level.WARNING, "alreadyExists failed");
return false;
}
return alreadyExists;
}

@Override
public boolean registerWhenPublished() {
return true;
}

@Override
public List<String> getProviderInformation() {
return List.of("CrossRef", "https://status.crossref.org/");
}

@Override
public String createIdentifier(DvObject dvObject) throws Throwable {
logger.info("CrossRef createIdentifier");
if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) {
dvObject = generatePid(dvObject);
}
String identifier = getIdentifier(dvObject);
try {
String retString = crossRefDOIRegisterService.reserveIdentifier(identifier, dvObject);
logger.log(Level.FINE, "CrossRef create DOI identifier retString : " + retString);
return retString;
} catch (Exception e) {
logger.log(Level.WARNING, "CrossRef Identifier not created: create failed", e);
throw e;
}
}

@Override
public Map<String, String> getIdentifierMetadata(DvObject dvObject) {
logger.info("CrossRef getIdentifierMetadata");
String identifier = getIdentifier(dvObject);
Map<String, String> metadata = new HashMap<>();
try {
metadata = crossRefDOIRegisterService.getMetadata(identifier);
} catch (Exception e) {
logger.log(Level.WARNING, "getIdentifierMetadata failed", e);
}
return metadata;
}

@Override
public String modifyIdentifierTargetURL(DvObject dvObject) throws Exception {
logger.info("CrossRef modifyIdentifier");
String identifier = getIdentifier(dvObject);
try {
crossRefDOIRegisterService.modifyIdentifier(identifier, dvObject);
} catch (Exception e) {
logger.log(Level.WARNING, "modifyMetadata failed", e);
throw e;
}
return identifier;
}

@Override
public void deleteIdentifier(DvObject dvo) throws Exception {
logger.info("CrossRef deleteIdentifier");
}

@Override
public boolean publicizeIdentifier(DvObject dvObject) {
logger.info("CrossRef updateIdentifierStatus");
if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) {
dvObject = generatePid(dvObject);
}
String identifier = getIdentifier(dvObject);

try {
crossRefDOIRegisterService.reserveIdentifier(identifier, dvObject);
return true;
} catch (Exception e) {
logger.log(Level.WARNING, "modifyMetadata failed: " + e.getMessage(), e);
return false;
}
}

@Override
public String getProviderType() {
return TYPE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package edu.harvard.iq.dataverse.pidproviders.doi.crossref;

import com.google.auto.service.AutoService;
import edu.harvard.iq.dataverse.pidproviders.PidProvider;
import edu.harvard.iq.dataverse.pidproviders.PidProviderFactory;
import edu.harvard.iq.dataverse.settings.JvmSettings;
import edu.harvard.iq.dataverse.util.SystemConfig;

@AutoService(PidProviderFactory.class)
public class CrossRefDOIProviderFactory implements PidProviderFactory {

@Override
public PidProvider createPidProvider(String providerId) {
String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId);
if (!providerType.equals(CrossRefDOIProvider.TYPE)) {
// Being asked to create a non-CrossRef provider
return null;
}
String providerLabel = JvmSettings.PID_PROVIDER_LABEL.lookup(providerId);
String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerId);
String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerId).orElse("");
String identifierGenerationStyle = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE
.lookupOptional(providerId).orElse("randomString");
String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerId)
.orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString());
String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse("");
String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse("");

String baseUrl = JvmSettings.CROSSREF_URL.lookup(providerId);
String apiUrl = JvmSettings.CROSSREF_REST_API_URL.lookup(providerId);
String username = JvmSettings.CROSSREF_USERNAME.lookup(providerId);
String password = JvmSettings.CROSSREF_PASSWORD.lookup(providerId);
String depositor = JvmSettings.CROSSREF_DEPOSITOR.lookup(providerId);
String depositorEmail = JvmSettings.CROSSREF_DEPOSITOR_EMAIL.lookup(providerId);

return new CrossRefDOIProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle,
datafilePidFormat, managedList, excludedList, baseUrl, apiUrl, username, password, depositor, depositorEmail);
}

public String getType() {
return CrossRefDOIProvider.TYPE;
}
}
Loading

0 comments on commit ec882e3

Please sign in to comment.