-
Notifications
You must be signed in to change notification settings - Fork 501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crossref as a DOI provider (experimental) #10806
Changes from 6 commits
e1bf3c3
6df7513
74bf796
eeb260e
5d4302c
ac1b23c
37c7411
7946c5a
405da59
4939183
0fe339d
8dfd5f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -617,6 +617,15 @@ this provider. | |
- :ref:`dataverse.pid.ezid.username` | ||
- :ref:`dataverse.pid.ezid.password` | ||
|
||
**JVM Options for CrossRef:** | ||
|
||
- :ref:`dataverse.pid.crossref.url` | ||
- :ref:`dataverse.pid.crossref.rest-api-url` | ||
- :ref:`dataverse.pid.crossref.username` | ||
- :ref:`dataverse.pid.crossref.password` | ||
- :ref:`dataverse.pid.crossref.depositor` | ||
- :ref:`dataverse.pid.crossref.depositor-email` | ||
|
||
**Database Settings:** | ||
|
||
- :ref:`:DoiProvider <:DoiProvider>` | ||
|
@@ -2841,6 +2850,50 @@ should delete the old JVM option and the wrapped password alias, then recreate | |
as shown for :ref:`dataverse.pid.datacite.password` but with the EZID alias | ||
name. | ||
|
||
.. _dataverse.pid.crossref.url: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are about legacy support which is no longer implemented - they can all be removed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
|
||
dataverse.pid.crossref.url | ||
++++++++++++++++++++++++++ | ||
|
||
CrossRef url used to post metadata. | ||
|
||
.. _dataverse.pid.crossref.rest-api-url: | ||
|
||
dataverse.pid.crossref.rest-api-url | ||
+++++++++++++++++++++++++++++++++++ | ||
|
||
CrossRef API url to retrieve metadata information | ||
|
||
.. _dataverse.pid.crossref.username: | ||
|
||
dataverse.pid.crossref.username | ||
+++++++++++++++++++++++++++++++ | ||
|
||
CrossRef uses `HTTP Basic authentication <https://en.wikipedia.org/wiki/Basic_access_authentication>`_ | ||
for their APIs. | ||
- Used in conjunction with :ref:`dataverse.pid.crossref.url` and :ref:`dataverse.pid.crossref.password`. | ||
|
||
.. _dataverse.pid.crossref.password: | ||
|
||
dataverse.pid.crossref.password | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you edit this to move it to the multiple provide section, please add a note like the one on DataCite suggesting that more secure options should be used (versus having the password as a plain text jvm-option) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The PR was made before multiPid was supported/before docs were improved with that, etc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will modify the doc |
||
+++++++++++++++++++++++++++++++ | ||
|
||
- Used in conjunction with :ref:`dataverse.pid.crossref.url` and :ref:`dataverse.pid.crossref.username`. | ||
|
||
.. _dataverse.pid.crossref.depositor: | ||
|
||
dataverse.pid.crossref.depositor | ||
++++++++++++++++++++++++++++++++ | ||
|
||
The entity, such as a person or organization, that deposited the Dataset in the repository | ||
|
||
.. _dataverse.pid.crossref.depositor-email: | ||
|
||
dataverse.pid.crossref.depositor-email | ||
++++++++++++++++++++++++++++++++++++++ | ||
|
||
Contact email to the indicated Depositor | ||
|
||
.. _dataverse.timerServer: | ||
|
||
dataverse.timerServer | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,6 @@ | |
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
import java.util.Optional; | ||
import java.util.ServiceLoader; | ||
import java.util.logging.Level; | ||
|
@@ -30,6 +29,7 @@ | |
import edu.harvard.iq.dataverse.DvObjectServiceBean; | ||
import edu.harvard.iq.dataverse.GlobalId; | ||
import edu.harvard.iq.dataverse.pidproviders.doi.UnmanagedDOIProvider; | ||
import edu.harvard.iq.dataverse.pidproviders.doi.crossref.CrossRefDOIProviderFactory; | ||
import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DataCiteDOIProvider; | ||
import edu.harvard.iq.dataverse.pidproviders.doi.ezid.EZIdDOIProvider; | ||
import edu.harvard.iq.dataverse.pidproviders.doi.fake.FakeDOIProvider; | ||
|
@@ -188,6 +188,9 @@ private void loadProviders() { | |
legacy = new FakeDOIProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, | ||
dataFilePidFormat, "", ""); | ||
break; | ||
case "CrossRef": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you should drop this. If you want to support legacy still, this section should be doing like the DataCite legacy section above to read the legacy-style options and feed them into the provider directly (creating a new CrossRefDOIProvider rather than calling a factory method). Again - probably better to drop it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will remove |
||
legacy = new CrossRefDOIProviderFactory().createPidProvider(JvmSettings.PID_DEFAULT_PROVIDER.lookup()); | ||
break; | ||
} | ||
break; | ||
case "hdl": | ||
|
@@ -247,4 +250,4 @@ public PidProvider getDefaultPidGenerator() { | |
return PidUtil.getPidProvider(protocol, authority, shoulder); | ||
} | ||
} | ||
} | ||
} |
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 CrossRefDOIPidProvider extends AbstractDOIProvider { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other DOI providers drop the Pid part of the name (or use DOI instead of Pid since it is the type of Pid they support), so this would be more consistent as CrossRefDOIProvider. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renaming |
||
private static final Logger logger = Logger.getLogger(CrossRefDOIPidProvider.class.getCanonicalName()); | ||
|
||
public static final String TYPE = "crossref"; | ||
|
||
CrossRefDOIRegisterService crossRefDOIRegisterService; | ||
|
||
public CrossRefDOIPidProvider(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(CrossRefDOIPidProvider.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 CrossRefDOIPidProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, | ||
datafilePidFormat, managedList, excludedList, baseUrl, apiUrl, username, password, depositor, depositorEmail); | ||
} | ||
|
||
public String getType() { | ||
return CrossRefDOIPidProvider.TYPE; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation, and some of the code, is for 'legacy' single pid configuration but I think we could/should only support handling the new multipid way of doing config. Although I think you've added it, I think it's reasonable to not support the legacy style at all for cross ref (since the idea of legacy was to support people who had already deployed with the old single provider jvm options and no one could have used CrossRef before now (except the developer's group).
To change the docs - see the DataCite section in the guide and add the info there (probably right after DataCite/before Handle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will modify the doc