From fae28d54e10843751ab3e3f33fc9665a1c7f76fd Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 22 Dec 2023 13:21:41 -0500 Subject: [PATCH 001/113] Switch to per-pid-provider settings --- .../iq/dataverse/DOIDataCiteServiceBean.java | 6 ++-- .../iq/dataverse/DOIEZIdServiceBean.java | 6 ++-- .../iq/dataverse/HandlenetServiceBean.java | 12 +++---- .../PermaLinkPidProviderServiceBean.java | 2 +- .../iq/dataverse/settings/JvmSettings.java | 33 ++++++++++--------- .../META-INF/microprofile-config.properties | 8 ++--- .../dataverse/settings/JvmSettingsTest.java | 17 +++------- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java index 48786b41824..3e770a2cc49 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java @@ -186,9 +186,9 @@ public void deleteIdentifier(DvObject dvObject) throws IOException, HttpExceptio private void deleteDraftIdentifier(DvObject dvObject) throws IOException { //ToDo - incorporate into DataCiteRESTfulClient - String baseUrl = JvmSettings.DATACITE_REST_API_URL.lookup(); - String username = JvmSettings.DATACITE_USERNAME.lookup(); - String password = JvmSettings.DATACITE_PASSWORD.lookup(); + String baseUrl = JvmSettings.DATACITE_REST_API_URL.lookup("datacite"); + String username = JvmSettings.DATACITE_USERNAME.lookup("datacite"); + String password = JvmSettings.DATACITE_PASSWORD.lookup("datacite"); GlobalId doi = dvObject.getGlobalId(); /** * Deletes the DOI from DataCite if it can. Returns 204 if PID was deleted diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java index 86b74b72f30..d44a4f78cc6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java @@ -21,7 +21,7 @@ public class DOIEZIdServiceBean extends DOIServiceBean { EZIDService ezidService; // This has a sane default in microprofile-config.properties - private final String baseUrl = JvmSettings.EZID_API_URL.lookup(); + private final String baseUrl = JvmSettings.EZID_API_URL.lookup("ezid"); public DOIEZIdServiceBean() { // Creating the service doesn't do any harm, just initializing some object data here. @@ -31,8 +31,8 @@ public DOIEZIdServiceBean() { try { // These have (obviously) no default, but still are optional to make the provider optional - String username = JvmSettings.EZID_USERNAME.lookupOptional().orElse(null); - String password = JvmSettings.EZID_PASSWORD.lookupOptional().orElse(null); + String username = JvmSettings.EZID_USERNAME.lookupOptional("ezid").orElse(null); + String password = JvmSettings.EZID_PASSWORD.lookupOptional("ezid").orElse(null); if (username != null ^ password != null) { logger.log(Level.WARNING, "You must give both username and password. Will not try to login."); diff --git a/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java index 4942db9e7ec..767a099a001 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java @@ -70,7 +70,7 @@ public class HandlenetServiceBean extends AbstractGlobalIdServiceBean { private static final Logger logger = Logger.getLogger(HandlenetServiceBean.class.getCanonicalName()); public static final String HDL_PROTOCOL = "hdl"; - int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class); + int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); public static final String HTTP_HDL_RESOLVER_URL = "http://hdl.handle.net/"; public static final String HDL_RESOLVER_URL = "https://hdl.handle.net/"; @@ -231,8 +231,8 @@ private ResolutionRequest buildResolutionRequest(final String handle) { private PublicKeyAuthenticationInfo getAuthInfo(String handlePrefix) { logger.log(Level.FINE,"getAuthInfo"); byte[] key = null; - String adminCredFile = JvmSettings.HANDLENET_KEY_PATH.lookup(); - int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class); + String adminCredFile = JvmSettings.HANDLENET_KEY_PATH.lookup("handlenet"); + int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); key = readKey(adminCredFile); PrivateKey privkey = null; @@ -278,7 +278,7 @@ private PrivateKey readPrivKey(byte[] key, final String file) { try { byte[] secKey = null; if ( Util.requiresSecretKey(key) ) { - String secret = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup(); + String secret = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup("handlenet"); secKey = secret.getBytes(StandardCharsets.UTF_8); } key = Util.decrypt(key, secKey); @@ -348,8 +348,8 @@ public void deleteIdentifier(DvObject dvObject) throws Exception { String handle = getDvObjectHandle(dvObject); String authHandle = getAuthenticationHandle(dvObject); - String adminCredFile = JvmSettings.HANDLENET_KEY_PATH.lookup(); - int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class); + String adminCredFile = JvmSettings.HANDLENET_KEY_PATH.lookup("handlenet"); + int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); byte[] key = readKey(adminCredFile); PrivateKey privkey = readPrivKey(key, adminCredFile); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java index d145a7ec106..faf3e4857d2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java @@ -36,7 +36,7 @@ public class PermaLinkPidProviderServiceBean extends AbstractGlobalIdServiceBean //ToDo - handle dataset/file defaults for local system public static final String PERMA_RESOLVER_URL = JvmSettings.PERMALINK_BASEURL - .lookupOptional() + .lookupOptional("permalink") .orElse(SystemConfig.getDataverseSiteUrlStatic()); String authority = null; diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index 3bc06738a7e..b84d48fd5dd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -91,30 +91,33 @@ public enum JvmSettings { // PERSISTENT IDENTIFIER SETTINGS SCOPE_PID(PREFIX, "pid"), + SCOPE_PID_PROVIDER(SCOPE_PID), + PID_PROVIDER_TYPE(SCOPE_PID_PROVIDER, "type"), + PID_PROVIDER_NAME(SCOPE_PID_PROVIDER, "name"), // PROVIDER EZID (legacy) - these settings were formerly kept together with DataCite ones - SCOPE_PID_EZID(SCOPE_PID, "ezid"), - EZID_API_URL(SCOPE_PID_EZID, "api-url", "doi.baseurlstring"), - EZID_USERNAME(SCOPE_PID_EZID, "username", "doi.username"), - EZID_PASSWORD(SCOPE_PID_EZID, "password", "doi.password"), + SCOPE_PID_EZID(SCOPE_PID_PROVIDER, "ezid"), + EZID_API_URL(SCOPE_PID_EZID, "api-url"), + EZID_USERNAME(SCOPE_PID_EZID, "username"), + EZID_PASSWORD(SCOPE_PID_EZID, "password"), // PROVIDER DATACITE - SCOPE_PID_DATACITE(SCOPE_PID, "datacite"), - DATACITE_MDS_API_URL(SCOPE_PID_DATACITE, "mds-api-url", "doi.baseurlstring"), - DATACITE_REST_API_URL(SCOPE_PID_DATACITE, "rest-api-url", "doi.dataciterestapiurlstring", "doi.mdcbaseurlstring"), - DATACITE_USERNAME(SCOPE_PID_DATACITE, "username", "doi.username"), - DATACITE_PASSWORD(SCOPE_PID_DATACITE, "password", "doi.password"), + SCOPE_PID_DATACITE(SCOPE_PID_PROVIDER, "datacite"), + DATACITE_MDS_API_URL(SCOPE_PID_DATACITE, "mds-api-url"), + DATACITE_REST_API_URL(SCOPE_PID_DATACITE, "rest-api-url"), + DATACITE_USERNAME(SCOPE_PID_DATACITE, "username"), + DATACITE_PASSWORD(SCOPE_PID_DATACITE, "password"), // PROVIDER PERMALINK - SCOPE_PID_PERMALINK(SCOPE_PID, "permalink"), - PERMALINK_BASEURL(SCOPE_PID_PERMALINK, "base-url", "perma.baseurlstring"), + SCOPE_PID_PERMALINK(SCOPE_PID_PROVIDER, "permalink"), + PERMALINK_BASEURL(SCOPE_PID_PERMALINK, "base-url"), // PROVIDER HANDLE - SCOPE_PID_HANDLENET(SCOPE_PID, "handlenet"), - HANDLENET_INDEX(SCOPE_PID_HANDLENET, "index", "dataverse.handlenet.index"), + SCOPE_PID_HANDLENET(SCOPE_PID_PROVIDER, "handlenet"), + HANDLENET_INDEX(SCOPE_PID_HANDLENET, "index"), SCOPE_PID_HANDLENET_KEY(SCOPE_PID_HANDLENET, "key"), - HANDLENET_KEY_PATH(SCOPE_PID_HANDLENET_KEY, "path", "dataverse.handlenet.admcredfile"), - HANDLENET_KEY_PASSPHRASE(SCOPE_PID_HANDLENET_KEY, "passphrase", "dataverse.handlenet.admprivphrase"), + HANDLENET_KEY_PATH(SCOPE_PID_HANDLENET_KEY, "path"), + HANDLENET_KEY_PASSPHRASE(SCOPE_PID_HANDLENET_KEY, "passphrase"), // SPI SETTINGS SCOPE_SPI(PREFIX, "spi"), diff --git a/src/main/resources/META-INF/microprofile-config.properties b/src/main/resources/META-INF/microprofile-config.properties index ec8427795ee..0a769e06573 100644 --- a/src/main/resources/META-INF/microprofile-config.properties +++ b/src/main/resources/META-INF/microprofile-config.properties @@ -52,14 +52,14 @@ dataverse.oai.server.maxsets=100 # PERSISTENT IDENTIFIER PROVIDERS # EZID -dataverse.pid.ezid.api-url=https://ezid.cdlib.org +dataverse.pid.ezid.ezid.api-url=https://ezid.cdlib.org # DataCite -dataverse.pid.datacite.mds-api-url=https://mds.test.datacite.org -dataverse.pid.datacite.rest-api-url=https://api.test.datacite.org +dataverse.pid.datacite.datacite.mds-api-url=https://mds.test.datacite.org +dataverse.pid.datacite.datacite.rest-api-url=https://api.test.datacite.org # Handle.Net -dataverse.pid.handlenet.index=300 +dataverse.pid.handlenet.handlenet.index=300 # AUTHENTICATION dataverse.auth.oidc.pkce.max-cache-size=10000 diff --git a/src/test/java/edu/harvard/iq/dataverse/settings/JvmSettingsTest.java b/src/test/java/edu/harvard/iq/dataverse/settings/JvmSettingsTest.java index 6b03f20fc41..f4494b7116e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/settings/JvmSettingsTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/settings/JvmSettingsTest.java @@ -17,22 +17,15 @@ void lookupSetting() { } @Test - @SystemProperty(key = "doi.username", value = "test") - void lookupSettingViaAlias() { - assertEquals("test", JvmSettings.DATACITE_USERNAME.lookup()); + @SystemProperty(key = "dataverse.pid.datacite.datacite.username", value = "test") + void lookupPidProviderSetting() { + assertEquals("test", JvmSettings.DATACITE_USERNAME.lookup("datacite")); } @Test - @SystemProperty(key = "doi.baseurlstring", value = "test") + @SystemProperty(key = "dataverse.ingest.rserve.port", value = "1234") void lookupSettingViaAliasWithDefaultInMPCFile() { - assertEquals("test", JvmSettings.DATACITE_MDS_API_URL.lookup()); - } - - @Test - @SystemProperty(key = "doi.dataciterestapiurlstring", value = "foo") - @SystemProperty(key = "doi.mdcbaseurlstring", value = "bar") - void lookupSettingViaAliasWithDefaultInMPCFileAndTwoAliases() { - assertEquals("foo", JvmSettings.DATACITE_REST_API_URL.lookup()); + assertEquals("1234", JvmSettings.RSERVE_PORT.lookup()); } } \ No newline at end of file From 80776685440076bcb9d1995ca7da3ed1604a5068 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 3 Jan 2024 10:11:34 -0500 Subject: [PATCH 002/113] partial refactor towards non-bean providers --- .../AbstractGlobalIdServiceBean.java | 3 +- .../iq/dataverse/DOIDataCiteServiceBean.java | 2 + .../iq/dataverse/DOIEZIdServiceBean.java | 2 + .../harvard/iq/dataverse/DOIServiceBean.java | 4 + .../iq/dataverse/GlobalIdServiceBean.java | 9 ++ .../pidproviders/DataCiteProviderFactory.java | 29 +++++ .../PermaLinkPidProviderServiceBean.java | 2 +- .../iq/dataverse/pidproviders/PidHelper.java | 43 ------- .../pidproviders/PidProviderFactory.java | 11 ++ .../pidproviders/PidProviderFactoryBean.java | 117 ++++++++++++++++++ .../iq/dataverse/pidproviders/PidUtil.java | 6 +- .../iq/dataverse/settings/JvmSettings.java | 6 + 12 files changed, 185 insertions(+), 49 deletions(-) create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java delete mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/PidHelper.java create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java diff --git a/src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java index f1bfc3e290b..7312df5ec17 100644 --- a/src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java @@ -33,7 +33,7 @@ public abstract class AbstractGlobalIdServiceBean implements GlobalIdServiceBean protected Boolean configured = null; public static String UNAVAILABLE = ":unav"; - + @Override public Map getMetadataForCreateIndicator(DvObject dvObjectIn) { logger.log(Level.FINE,"getMetadataForCreateIndicator(DvObject)"); @@ -697,4 +697,5 @@ public boolean isConfigured() { return configured.booleanValue(); } } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java index 3e770a2cc49..72aab51fc19 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java @@ -32,6 +32,8 @@ public class DOIDataCiteServiceBean extends DOIServiceBean { private static final String RESERVED = "reserved"; private static final String DRAFT = "draft"; + public static final String TYPE = "datacite"; + @EJB DOIDataCiteRegisterService doiDataCiteRegisterService; diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java index d44a4f78cc6..af2a1d60be1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java @@ -20,6 +20,8 @@ public class DOIEZIdServiceBean extends DOIServiceBean { EZIDService ezidService; + public static final String TYPE = "ezid"; + // This has a sane default in microprofile-config.properties private final String baseUrl = JvmSettings.EZID_API_URL.lookup("ezid"); diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java index 0182c745cd0..56131872100 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java @@ -75,4 +75,8 @@ public boolean isConfigured() { protected String getProviderKeyName() { return null; } + + public String getProtocol() { + return DOI_PROTOCOL; + } } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java index aebf13778c3..06438dfb27d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java @@ -65,6 +65,12 @@ public interface GlobalIdServiceBean { String getUrlPrefix(); String getSeparator(); + String getProtocol(); + String getProviderType(); + String getName(); + + + //ToDo - now need to get the correct provider based on the protocol, authority, and shoulder (for new pids)/indentifier (for existing pids) static GlobalIdServiceBean getBean(String protocol, CommandContext ctxt) { final Function protocolHandler = BeanDispatcher.DISPATCHER.get(protocol); if ( protocolHandler != null ) { @@ -111,6 +117,7 @@ public static Optional parse(String identifierString) { * {@code null} if parsing failed. */ public GlobalId parsePersistentId(String identifierString); + public GlobalId parsePersistentId(String protocol, String authority, String identifier); @@ -177,6 +184,7 @@ static boolean checkDOIAuthority(String doiAuthority){ return true; } + } @@ -194,6 +202,7 @@ static boolean checkDOIAuthority(String doiAuthority){ * Static utility class for dispatching implementing beans, based on protocol and providers. * @author michael */ +// FWIW: For lists of PIDs not managed by the provider covered by authority/shoulder, we need a way to add them to one provider and exlude them if another registered provider handles their authority/shoulder (probably rare?) class BeanDispatcher { static final Map> DISPATCHER = new HashMap<>(); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java new file mode 100644 index 00000000000..08d51815d2e --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -0,0 +1,29 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.DOIDataCiteServiceBean; +import edu.harvard.iq.dataverse.GlobalIdServiceBean; +import edu.harvard.iq.dataverse.settings.JvmSettings; + +class DataCiteProviderFactory extends PidProviderFactory { + + public GlobalIdServiceBean createProvider(String providerName) { + String providerType=JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + if(!providerType.equals(DOIDataCiteServiceBean.TYPE)) { + //Being asked to create a non-DataCite provider + return null; + } + String providerAuthority=JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); + String providerShoulder=JvmSettings.PID_PROVIDER_SHOULDER.lookup(providerName); + String mdsUrl=JvmSettings.DATACITE_MDS_API_URL.lookup(providerName); + String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerName); + String username = JvmSettings.DATACITE_USERNAME.lookup(providerName); + String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); + String[] whitelist = JvmSettings.PID_PROVIDER_WHITELIST.lookup(providerName).split(","); + + return new DOIDataCiteServiceBean(providerAuthority, providerShoulder, mdsUrl, apiUrl, username, password); + } + + public String getType() { + return DOIDataCiteServiceBean.TYPE; + } +} diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java index faf3e4857d2..2d0539bcfa3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java @@ -45,7 +45,7 @@ public class PermaLinkPidProviderServiceBean extends AbstractGlobalIdServiceBean @PostConstruct private void init() { if(PERMA_PROTOCOL.equals(settingsService.getValueForKey(Key.Protocol))){ - authority = settingsService.getValueForKey(Key.Authority); + authority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup("permalink"); configured=true; }; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidHelper.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidHelper.java deleted file mode 100644 index 5bc855a9593..00000000000 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidHelper.java +++ /dev/null @@ -1,43 +0,0 @@ -package edu.harvard.iq.dataverse.pidproviders; - -import java.util.Arrays; -import jakarta.annotation.PostConstruct; -import jakarta.ejb.EJB; -import jakarta.ejb.Singleton; -import jakarta.ejb.Startup; - -import edu.harvard.iq.dataverse.DOIDataCiteServiceBean; -import edu.harvard.iq.dataverse.DOIEZIdServiceBean; -import edu.harvard.iq.dataverse.HandlenetServiceBean; - - /** - * This is a small helper bean - * As it is a singleton and built at application start (=deployment), it will inject the (stateless) - * dataverse service into the BrandingUtil once it's ready. - */ - @Startup - @Singleton - public class PidHelper { - - @EJB - DOIDataCiteServiceBean datacitePidSvc; - @EJB - DOIEZIdServiceBean ezidPidSvc; - @EJB - HandlenetServiceBean handlePidSvc; - @EJB - FakePidProviderServiceBean fakePidSvc; - @EJB - PermaLinkPidProviderServiceBean permaPidSvc; - @EJB - UnmanagedDOIServiceBean unmanagedDOISvc; - @EJB - UnmanagedHandlenetServiceBean unmanagedHandleSvc; - - @PostConstruct - public void listServices() { - PidUtil.addAllToProviderList(Arrays.asList(datacitePidSvc, ezidPidSvc, handlePidSvc, permaPidSvc, fakePidSvc)); - PidUtil.addAllToUnmanagedProviderList(Arrays.asList(unmanagedDOISvc, unmanagedHandleSvc)); - } - - } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java new file mode 100644 index 00000000000..dc2e34d7abd --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java @@ -0,0 +1,11 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.GlobalIdServiceBean; + +public interface PidProviderFactory { + + public String getType(); + + public GlobalIdServiceBean createPidProvider(String name); + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java new file mode 100644 index 00000000000..f14f5318034 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -0,0 +1,117 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.eclipse.microprofile.config.ConfigProvider; + +import jakarta.annotation.PostConstruct; +import jakarta.ejb.EJB; +import jakarta.ejb.Singleton; +import jakarta.ejb.Startup; + +import edu.harvard.iq.dataverse.DOIDataCiteServiceBean; +import edu.harvard.iq.dataverse.DOIEZIdServiceBean; +import edu.harvard.iq.dataverse.GlobalIdServiceBean; +import edu.harvard.iq.dataverse.HandlenetServiceBean; +import edu.harvard.iq.dataverse.export.ExportService; +import edu.harvard.iq.dataverse.settings.JvmSettings; +import io.gdcc.spi.export.Exporter; + +/** + * This Bean loads all of the PidProviderFactory types available (e.g. EZID, + * DataCite, Handle, PermaLink) and then reads the configuration to load + * particular PidProviders (e.g. a DataCite provider with a specific + * authority/shoulder, username/password, etc.) + */ +@Startup +@Singleton +public class PidProviderFactoryBean { + + private static final Logger logger = Logger.getLogger(PidProviderFactoryBean.class.getCanonicalName()); + + private ServiceLoader loader; + private Map pidProviderFactoryMap = new HashMap<>(); + + @PostConstruct + public void init() { + loadProviderFactories(); + loadProviders(); + } + + private void loadProviderFactories() { + /* + * Step 1 - find the PROVIDERS dir and add all jar files there to a class loader + */ + List jarUrls = new ArrayList<>(); + Optional providerPathSetting = JvmSettings.PROVIDERS_DIRECTORY.lookupOptional(String.class); + if (providerPathSetting.isPresent()) { + Path exporterDir = Paths.get(providerPathSetting.get()); + // Get all JAR files from the configured directory + try (DirectoryStream stream = Files.newDirectoryStream(exporterDir, "*.jar")) { + // Using the foreach loop here to enable catching the URI/URL exceptions + for (Path path : stream) { + logger.log(Level.FINE, "Adding {0}", path.toUri().toURL()); + // This is the syntax required to indicate a jar file from which classes should + // be loaded (versus a class file). + jarUrls.add(new URL("jar:" + path.toUri().toURL() + "!/")); + } + } catch (IOException e) { + logger.warning("Problem accessing external Exporters: " + e.getLocalizedMessage()); + } + } + URLClassLoader cl = URLClassLoader.newInstance(jarUrls.toArray(new URL[0]), this.getClass().getClassLoader()); + + /* + * Step 2 - load all PidProcviderFactories that can be found, using the jars as + * additional sources + */ + loader = ServiceLoader.load(PidProviderFactory.class, cl); + /* + * Step 3 - Fill pidProviderFactoryMap with type as the key, allow external + * factories to replace internal ones for the same type. FWIW: From the logging + * it appears that ServiceLoader returns classes in ~ alphabetical order rather + * than by class loader, so internal classes handling a given providerName may + * be processed before or after external ones. + */ + loader.forEach(providerFactory -> { + String type = providerFactory.getType(); + // If no entry for this providerName yet or if it is an external exporter + if (!pidProviderFactoryMap.containsKey(type) || providerFactory.getClass().getClassLoader().equals(cl)) { + pidProviderFactoryMap.put(type, providerFactory); + } + logger.log(Level.FINE, + "Loaded PidProviderFactory of type: " + type + " from " + + providerFactory.getClass().getCanonicalName() + " and classloader: " + + providerFactory.getClass().getClassLoader().getClass().getCanonicalName()); + }); + } + + private void loadProviders() { + String[] providers = JvmSettings.PID_PROVIDERS.lookup(String[].class); + for (String name : providers) { + String type = JvmSettings.PID_PROVIDER_TYPE.lookup(name); + if (pidProviderFactoryMap.containsKey(type)) { + GlobalIdServiceBean provider = pidProviderFactoryMap.get(type).createPidProvider(name); + PidUtil.addToProviderList(provider); + } + } + PidUtil.addAllToUnmanagedProviderList(Arrays.asList(unmanagedDOISvc, unmanagedHandleSvc)); + } + +} \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 78305648f67..b67b462616d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -122,10 +122,8 @@ private static String acceptOnlyDoi(GlobalId globalId) { static Map providerMap = new HashMap(); static Map unmanagedProviderMap = new HashMap(); - public static void addAllToProviderList(List list) { - for (GlobalIdServiceBean pidProvider : list) { - providerMap.put(pidProvider.getProviderInformation().get(0), pidProvider); - } + public static void addToProviderList(GlobalIdServiceBean pidProvider) { + providerMap.put(pidProvider.getName(), pidProvider); } public static void addAllToUnmanagedProviderList(List list) { diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index b84d48fd5dd..7eaa7e03488 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -91,9 +91,15 @@ public enum JvmSettings { // PERSISTENT IDENTIFIER SETTINGS SCOPE_PID(PREFIX, "pid"), + PID_PROVIDERS(SCOPE_PID, "providers"), + PROVIDERS_DIRECTORY(SCOPE_PID, "provider-implementations-directory"), SCOPE_PID_PROVIDER(SCOPE_PID), PID_PROVIDER_TYPE(SCOPE_PID_PROVIDER, "type"), PID_PROVIDER_NAME(SCOPE_PID_PROVIDER, "name"), + PID_PROVIDER_AUTHORITY(SCOPE_PID_PROVIDER, "authority"), + PID_PROVIDER_SHOULDER(SCOPE_PID_PROVIDER, "shoulder"), + PID_PROVIDER_MANAGED_LIST(SCOPE_PID_PROVIDER, "managed-list"), + PID_PROVIDER_EXCLUDED_LIST(SCOPE_PID_PROVIDER, "excluded-list"), // PROVIDER EZID (legacy) - these settings were formerly kept together with DataCite ones SCOPE_PID_EZID(SCOPE_PID_PROVIDER, "ezid"), From 61f55bbac4d26aaf7535322f4fc647f6b9b93060 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 3 Jan 2024 12:02:28 -0500 Subject: [PATCH 003/113] ~auto refactor name/package, remove bean status --- .../harvard/iq/dataverse/DataCitation.java | 5 +- .../edu/harvard/iq/dataverse/DatasetPage.java | 3 +- .../iq/dataverse/DatasetServiceBean.java | 6 ++- .../iq/dataverse/EjbDataverseEngine.java | 27 ++++++----- .../edu/harvard/iq/dataverse/GlobalId.java | 2 +- .../iq/dataverse/S3PackageImporter.java | 5 +- .../edu/harvard/iq/dataverse/api/Admin.java | 6 +-- .../harvard/iq/dataverse/api/Dataverses.java | 6 +-- .../harvard/iq/dataverse/api/LDNInbox.java | 16 +++---- .../api/imports/ImportGenericServiceBean.java | 34 ++++++------- .../importer/filesystem/FileRecordWriter.java | 6 +-- .../engine/command/CommandContext.java | 20 ++++---- .../impl/AbstractCreateDatasetCommand.java | 3 +- .../command/impl/AbstractDatasetCommand.java | 4 +- .../impl/AbstractSubmitToArchiveCommand.java | 2 +- .../command/impl/CreateNewDatasetCommand.java | 6 +-- .../command/impl/DeleteDataFileCommand.java | 4 +- .../engine/command/impl/DeletePidCommand.java | 4 +- .../command/impl/DestroyDatasetCommand.java | 5 +- .../FinalizeDatasetPublicationCommand.java | 5 +- .../impl/GrantSuperuserStatusCommand.java | 2 +- .../command/impl/ImportDatasetCommand.java | 6 +-- .../command/impl/PublishDatasetCommand.java | 2 +- .../command/impl/RegisterDvObjectCommand.java | 13 ++--- .../command/impl/ReservePidCommand.java | 4 +- .../impl/RevokeSuperuserStatusCommand.java | 2 +- .../impl/UpdateDatasetTargetURLCommand.java | 5 +- .../UpdateDvObjectPIDMetadataCommand.java | 4 +- .../export/InternalExportDataProvider.java | 3 +- .../export/openaire/OpenAireExportUtil.java | 8 ++-- .../AbstractPidProvider.java} | 29 +++++++---- .../DOIEZIdProvider.java} | 24 ++++++++-- .../DOIProvider.java} | 9 ++-- .../DataCiteDOIProvider.java} | 28 +++++++++-- .../pidproviders/DataCiteProviderFactory.java | 10 ++-- ...rServiceBean.java => FakeDOIProvider.java} | 18 +++++-- .../HandlePidProvider.java} | 31 ++++++++++-- ...iceBean.java => PermaLinkPidProvider.java} | 32 ++++++++++--- .../PidProvider.java} | 35 +++++++------- .../pidproviders/PidProviderFactory.java | 4 +- .../pidproviders/PidProviderFactoryBean.java | 7 +-- .../iq/dataverse/pidproviders/PidUtil.java | 39 +++++++-------- ...iceBean.java => UnmanagedDOIProvider.java} | 20 ++++++-- .../UnmanagedHandlenetServiceBean.java | 23 +++++---- .../datacite}/DOIDataCiteRegisterCache.java | 2 +- .../datacite}/DOIDataCiteRegisterService.java | 33 ++++++++----- .../datacite}/DataCiteRESTfullClient.java | 2 +- .../iq/dataverse/util/json/JSONLDUtil.java | 4 +- .../harvard/iq/dataverse/GlobalIdTest.java | 8 ++-- .../PersistentIdentifierServiceBeanTest.java | 48 ++++++++++--------- .../dataaccess/GlobusOverlayAccessIOTest.java | 6 +-- .../dataaccess/RemoteOverlayAccessIOTest.java | 4 +- .../dataverse/engine/TestCommandContext.java | 17 ++++--- .../export/OpenAireExportUtilTest.java | 9 ++-- .../ExternalToolHandlerTest.java | 4 +- .../ExternalToolServiceBeanTest.java | 4 +- .../iq/dataverse/globus/GlobusUtilTest.java | 6 +-- .../dataverse/pidproviders/PidUtilTest.java | 10 ++-- .../search/IndexServiceBeanTest.java | 3 +- .../iq/dataverse/sitemap/SiteMapUtilTest.java | 10 ++-- .../iq/dataverse/util/UrlTokenUtilTest.java | 4 +- 61 files changed, 411 insertions(+), 290 deletions(-) rename src/main/java/edu/harvard/iq/dataverse/{AbstractGlobalIdServiceBean.java => pidproviders/AbstractPidProvider.java} (96%) rename src/main/java/edu/harvard/iq/dataverse/{DOIEZIdServiceBean.java => pidproviders/DOIEZIdProvider.java} (95%) rename src/main/java/edu/harvard/iq/dataverse/{DOIServiceBean.java => pidproviders/DOIProvider.java} (87%) rename src/main/java/edu/harvard/iq/dataverse/{DOIDataCiteServiceBean.java => pidproviders/DataCiteDOIProvider.java} (93%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{FakePidProviderServiceBean.java => FakeDOIProvider.java} (82%) rename src/main/java/edu/harvard/iq/dataverse/{HandlenetServiceBean.java => pidproviders/HandlePidProvider.java} (95%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{PermaLinkPidProviderServiceBean.java => PermaLinkPidProvider.java} (90%) rename src/main/java/edu/harvard/iq/dataverse/{GlobalIdServiceBean.java => pidproviders/PidProvider.java} (84%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{UnmanagedDOIServiceBean.java => UnmanagedDOIProvider.java} (84%) rename src/main/java/edu/harvard/iq/dataverse/{ => pidproviders/datacite}/DOIDataCiteRegisterCache.java (97%) rename src/main/java/edu/harvard/iq/dataverse/{ => pidproviders/datacite}/DOIDataCiteRegisterService.java (95%) rename src/main/java/edu/harvard/iq/dataverse/{ => pidproviders/datacite}/DataCiteRESTfullClient.java (99%) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataCitation.java b/src/main/java/edu/harvard/iq/dataverse/DataCitation.java index 9b4b89db44f..a012175deae 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataCitation.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataCitation.java @@ -7,6 +7,7 @@ import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.harvest.client.HarvestingClient; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; @@ -635,12 +636,12 @@ public Map getDataCiteMetadata() { String authorString = getAuthorsString(); if (authorString.isEmpty()) { - authorString = AbstractGlobalIdServiceBean.UNAVAILABLE; + authorString = AbstractPidProvider.UNAVAILABLE; } String producerString = getPublisher(); if (producerString.isEmpty()) { - producerString = AbstractGlobalIdServiceBean.UNAVAILABLE; + producerString = AbstractPidProvider.UNAVAILABLE; } metadata.put("datacite.creator", authorString); diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index b79f387f20b..04409ceb400 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -43,6 +43,7 @@ import edu.harvard.iq.dataverse.ingest.IngestServiceBean; import edu.harvard.iq.dataverse.license.LicenseServiceBean; import edu.harvard.iq.dataverse.metadataimport.ForeignMetadataImportServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; @@ -2120,7 +2121,7 @@ private String init(boolean initFull) { //Need to assign an identifier prior to calls to requestDirectUploadUrl if direct upload is used. if ( isEmpty(dataset.getIdentifier()) && systemConfig.directUploadEnabled(dataset) ) { CommandContext ctxt = commandEngine.getContext(); - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(ctxt); + PidProvider idServiceBean = PidProvider.getBean(ctxt); dataset.setIdentifier(idServiceBean.generateDatasetIdentifier(dataset)); } dataverseTemplates.addAll(dataverseService.find(ownerId).getTemplates()); diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java index c6df2a2e1ab..4ee74d0d53a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java @@ -19,6 +19,8 @@ import edu.harvard.iq.dataverse.export.ExportService; import edu.harvard.iq.dataverse.globus.GlobusServiceBean; import edu.harvard.iq.dataverse.harvest.server.OAIRecordServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; @@ -62,7 +64,7 @@ public class DatasetServiceBean implements java.io.Serializable { IndexServiceBean indexService; @EJB - DOIEZIdServiceBean doiEZIdServiceBean; + DOIEZIdProvider doiEZIdServiceBean; @EJB SettingsServiceBean settingsService; @@ -958,7 +960,7 @@ the changes from file ingest (which may be happening in parallel, also */ @Asynchronous public void obtainPersistentIdentifiersForDatafiles(Dataset dataset) { - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(dataset.getProtocol(), commandEngine.getContext()); + PidProvider idServiceBean = PidProvider.getBean(dataset.getProtocol(), commandEngine.getContext()); //If the Id type is sequential and Dependent then write file idenitifiers outside the command String datasetIdentifier = dataset.getIdentifier(); diff --git a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java index 5a689c06019..64c7380fab7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java +++ b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java @@ -17,8 +17,11 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.FakePidProviderServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -114,19 +117,19 @@ public class EjbDataverseEngine { DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels; @EJB - DOIEZIdServiceBean doiEZId; + DOIEZIdProvider doiEZId; @EJB - DOIDataCiteServiceBean doiDataCite; + DataCiteDOIProvider doiDataCite; @EJB - FakePidProviderServiceBean fakePidProvider; + FakeDOIProvider fakePidProvider; @EJB - HandlenetServiceBean handleNet; + HandlePidProvider handleNet; @EJB - PermaLinkPidProviderServiceBean permaLinkProvider; + PermaLinkPidProvider permaLinkProvider; @EJB SettingsServiceBean settings; @@ -484,27 +487,27 @@ public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels() { } @Override - public DOIEZIdServiceBean doiEZId() { + public DOIEZIdProvider doiEZId() { return doiEZId; } @Override - public DOIDataCiteServiceBean doiDataCite() { + public DataCiteDOIProvider doiDataCite() { return doiDataCite; } @Override - public FakePidProviderServiceBean fakePidProvider() { + public FakeDOIProvider fakePidProvider() { return fakePidProvider; } @Override - public HandlenetServiceBean handleNet() { + public HandlePidProvider handleNet() { return handleNet; } @Override - public PermaLinkPidProviderServiceBean permaLinkProvider() { + public PermaLinkPidProvider permaLinkProvider() { return permaLinkProvider; } diff --git a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java index 890b146a61c..182e3ee7f4f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java +++ b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java @@ -6,7 +6,7 @@ package edu.harvard.iq.dataverse; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.util.BundleUtil; import static edu.harvard.iq.dataverse.util.StringUtil.isEmpty; import java.net.MalformedURLException; diff --git a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java index 71318a0184a..d05e3d6f1db 100644 --- a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java @@ -17,6 +17,7 @@ import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectSummary; import edu.harvard.iq.dataverse.api.AbstractApiBean; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.FileUtil; import java.io.BufferedReader; @@ -204,7 +205,7 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t FileUtil.generateS3PackageStorageIdentifier(packageFile); - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(packageFile.getProtocol(), commandEngine.getContext()); + PidProvider idServiceBean = PidProvider.getBean(packageFile.getProtocol(), commandEngine.getContext()); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { String packageIdentifier = idServiceBean.generateDataFileIdentifier(packageFile); packageFile.setIdentifier(packageIdentifier); @@ -223,7 +224,7 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t if (!packageFile.isIdentifierRegistered()) { String doiRetString = ""; - idServiceBean = GlobalIdServiceBean.getBean(commandEngine.getContext()); + idServiceBean = PidProvider.getBean(commandEngine.getContext()); try { doiRetString = idServiceBean.createIdentifier(packageFile); } catch (Throwable e) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 48f9e19d835..5928096304f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -18,7 +18,6 @@ import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.validation.EMailValidator; import edu.harvard.iq.dataverse.EjbDataverseEngine; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.Template; import edu.harvard.iq.dataverse.TemplateServiceBean; import edu.harvard.iq.dataverse.UserServiceBean; @@ -97,6 +96,7 @@ import edu.harvard.iq.dataverse.engine.command.impl.DeleteTemplateCommand; import edu.harvard.iq.dataverse.engine.command.impl.RegisterDvObjectCommand; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.userdata.UserListMaker; import edu.harvard.iq.dataverse.userdata.UserListResult; @@ -1474,7 +1474,7 @@ public Response isOrcidEnabled() { public Response reregisterHdlToPID(@Context ContainerRequestContext crc, @PathParam("id") String id) { logger.info("Starting to reregister " + id + " Dataset Id. (from hdl to doi)" + new Date()); try { - if (settingsSvc.get(SettingsServiceBean.Key.Protocol.toString()).equals(HandlenetServiceBean.HDL_PROTOCOL)) { + if (settingsSvc.get(SettingsServiceBean.Key.Protocol.toString()).equals(HandlePidProvider.HDL_PROTOCOL)) { logger.info("Bad Request protocol set to handle " ); return error(Status.BAD_REQUEST, BundleUtil.getStringFromBundle("admin.api.migrateHDL.failure.must.be.set.for.doi")); } @@ -1487,7 +1487,7 @@ public Response reregisterHdlToPID(@Context ContainerRequestContext crc, @PathPa DataverseRequest r = createDataverseRequest(u); Dataset ds = findDatasetOrDie(id); - if (ds.getIdentifier() != null && !ds.getIdentifier().isEmpty() && ds.getProtocol().equals(HandlenetServiceBean.HDL_PROTOCOL)) { + if (ds.getIdentifier() != null && !ds.getIdentifier().isEmpty() && ds.getProtocol().equals(HandlePidProvider.HDL_PROTOCOL)) { execCommand(new RegisterDvObjectCommand(r, ds, true)); } else { return error(Status.BAD_REQUEST, BundleUtil.getStringFromBundle("admin.api.migrateHDL.failure.must.be.hdl.dataset")); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java index 6c1bf42c02a..91738a127bf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java @@ -15,7 +15,6 @@ import edu.harvard.iq.dataverse.authorization.DataverseRole; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.GuestbookResponseServiceBean; import edu.harvard.iq.dataverse.GuestbookServiceBean; import edu.harvard.iq.dataverse.MetadataBlock; @@ -74,6 +73,7 @@ import edu.harvard.iq.dataverse.engine.command.impl.UpdateExplicitGroupCommand; import edu.harvard.iq.dataverse.engine.command.impl.UpdateMetadataBlockFacetsCommand; import edu.harvard.iq.dataverse.engine.command.impl.ValidateDatasetJsonCommand; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; @@ -421,7 +421,7 @@ public Response importDataset(@Context ContainerRequestContext crc, String jsonB if (!GlobalId.verifyImportCharacters(pidParam)) { return badRequest("PID parameter contains characters that are not allowed by the Dataverse application. On import, the PID must only contain characters specified in this regex: " + BundleUtil.getStringFromBundle("pid.allowedCharacters")); } - Optional maybePid = GlobalIdServiceBean.parse(pidParam); + Optional maybePid = PidProvider.parse(pidParam); if (maybePid.isPresent()) { ds.setGlobalId(maybePid.get()); } else { @@ -496,7 +496,7 @@ public Response importDatasetDdi(@Context ContainerRequestContext crc, String xm if (!GlobalId.verifyImportCharacters(pidParam)) { return badRequest("PID parameter contains characters that are not allowed by the Dataverse application. On import, the PID must only contain characters specified in this regex: " + BundleUtil.getStringFromBundle("pid.allowedCharacters")); } - Optional maybePid = GlobalIdServiceBean.parse(pidParam); + Optional maybePid = PidProvider.parse(pidParam); if (maybePid.isPresent()) { ds.setGlobalId(maybePid.get()); } else { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java b/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java index 05d12f1083c..403470a63e1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java @@ -1,12 +1,9 @@ package edu.harvard.iq.dataverse.api; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetServiceBean; import edu.harvard.iq.dataverse.DataverseRoleServiceBean; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.MailServiceBean; import edu.harvard.iq.dataverse.RoleAssigneeServiceBean; import edu.harvard.iq.dataverse.RoleAssignment; @@ -15,6 +12,9 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.ip.IpAddress; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.json.JSONLDUtil; import edu.harvard.iq.dataverse.util.json.JsonLDNamespace; @@ -134,13 +134,13 @@ public Response acceptMessage(String body) { .getString("@id"); if (citedResource.getString("@type").equals(JsonLDTerm.schemaOrg("Dataset").getUrl())) { logger.fine("Raw PID: " + pid); - if (pid.startsWith(DOIServiceBean.DOI_RESOLVER_URL)) { - pid = pid.replace(DOIServiceBean.DOI_RESOLVER_URL, DOIServiceBean.DOI_PROTOCOL + ":"); - } else if (pid.startsWith(HandlenetServiceBean.HDL_RESOLVER_URL)) { - pid = pid.replace(HandlenetServiceBean.HDL_RESOLVER_URL, HandlenetServiceBean.HDL_PROTOCOL + ":"); + if (pid.startsWith(DOIProvider.DOI_RESOLVER_URL)) { + pid = pid.replace(DOIProvider.DOI_RESOLVER_URL, DOIProvider.DOI_PROTOCOL + ":"); + } else if (pid.startsWith(HandlePidProvider.HDL_RESOLVER_URL)) { + pid = pid.replace(HandlePidProvider.HDL_RESOLVER_URL, HandlePidProvider.HDL_PROTOCOL + ":"); } logger.fine("Protocol PID: " + pid); - Optional id = GlobalIdServiceBean.parse(pid); + Optional id = PidProvider.parse(pid); Dataset dataset = datasetSvc.findByGlobalId(pid); if (dataset != null) { JsonObject citingResource = Json.createObjectBuilder().add("@id", citingPID) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java index f7a6cf54dd5..ca84588b706 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java @@ -2,7 +2,6 @@ import com.google.gson.Gson; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetFieldCompoundValue; import edu.harvard.iq.dataverse.DatasetFieldConstant; @@ -11,13 +10,14 @@ import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.ForeignMetadataFieldMapping; import edu.harvard.iq.dataverse.ForeignMetadataFormatMapping; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.MetadataBlockServiceBean; import edu.harvard.iq.dataverse.api.dto.*; import edu.harvard.iq.dataverse.api.dto.FieldDTO; import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO; import edu.harvard.iq.dataverse.license.LicenseServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.StringUtil; import edu.harvard.iq.dataverse.util.json.JsonParseException; @@ -352,7 +352,7 @@ private String getOtherIdFromDTO(DatasetVersionDTO datasetVersionDTO) { if (!otherIds.isEmpty()) { // We prefer doi or hdl identifiers like "doi:10.7910/DVN/1HE30F" for (String otherId : otherIds) { - if (otherId.startsWith(DOIServiceBean.DOI_PROTOCOL) || otherId.startsWith(HandlenetServiceBean.HDL_PROTOCOL) || otherId.startsWith(DOIServiceBean.DOI_RESOLVER_URL) || otherId.startsWith(HandlenetServiceBean.HDL_RESOLVER_URL) || otherId.startsWith(DOIServiceBean.HTTP_DOI_RESOLVER_URL) || otherId.startsWith(HandlenetServiceBean.HTTP_HDL_RESOLVER_URL) || otherId.startsWith(DOIServiceBean.DXDOI_RESOLVER_URL) || otherId.startsWith(DOIServiceBean.HTTP_DXDOI_RESOLVER_URL)) { + if (otherId.startsWith(DOIProvider.DOI_PROTOCOL) || otherId.startsWith(HandlePidProvider.HDL_PROTOCOL) || otherId.startsWith(DOIProvider.DOI_RESOLVER_URL) || otherId.startsWith(HandlePidProvider.HDL_RESOLVER_URL) || otherId.startsWith(DOIProvider.HTTP_DOI_RESOLVER_URL) || otherId.startsWith(HandlePidProvider.HTTP_HDL_RESOLVER_URL) || otherId.startsWith(DOIProvider.DXDOI_RESOLVER_URL) || otherId.startsWith(DOIProvider.HTTP_DXDOI_RESOLVER_URL)) { return otherId; } } @@ -361,7 +361,7 @@ private String getOtherIdFromDTO(DatasetVersionDTO datasetVersionDTO) { try { HandleResolver hr = new HandleResolver(); hr.resolveHandle(otherId); - return HandlenetServiceBean.HDL_PROTOCOL + ":" + otherId; + return HandlePidProvider.HDL_PROTOCOL + ":" + otherId; } catch (HandleException e) { logger.fine("Not a valid handle: " + e.toString()); } @@ -388,7 +388,7 @@ public String reassignIdentifierAsGlobalId(String identifierString, DatasetDTO d String protocol = identifierString.substring(0, index1); - if (DOIServiceBean.DOI_PROTOCOL.equals(protocol) || HandlenetServiceBean.HDL_PROTOCOL.equals(protocol) || PermaLinkPidProviderServiceBean.PERMA_PROTOCOL.equals(protocol)) { + if (DOIProvider.DOI_PROTOCOL.equals(protocol) || HandlePidProvider.HDL_PROTOCOL.equals(protocol) || PermaLinkPidProvider.PERMA_PROTOCOL.equals(protocol)) { logger.fine("Processing hdl:- or doi:- or perma:-style identifier : "+identifierString); } else if ("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) { @@ -396,21 +396,21 @@ public String reassignIdentifierAsGlobalId(String identifierString, DatasetDTO d // We also recognize global identifiers formatted as global resolver URLs: //ToDo - refactor index1 always has -1 here so that we can use index1+1 later //ToDo - single map of protocol/url, are all three cases the same then? - if (identifierString.startsWith(HandlenetServiceBean.HDL_RESOLVER_URL) || identifierString.startsWith(HandlenetServiceBean.HTTP_HDL_RESOLVER_URL)) { + if (identifierString.startsWith(HandlePidProvider.HDL_RESOLVER_URL) || identifierString.startsWith(HandlePidProvider.HTTP_HDL_RESOLVER_URL)) { logger.fine("Processing Handle identifier formatted as a resolver URL: "+identifierString); - protocol = HandlenetServiceBean.HDL_PROTOCOL; - index1 = (identifierString.startsWith(HandlenetServiceBean.HDL_RESOLVER_URL)) ? HandlenetServiceBean.HDL_RESOLVER_URL.length() - 1 : HandlenetServiceBean.HTTP_HDL_RESOLVER_URL.length() - 1; + protocol = HandlePidProvider.HDL_PROTOCOL; + index1 = (identifierString.startsWith(HandlePidProvider.HDL_RESOLVER_URL)) ? HandlePidProvider.HDL_RESOLVER_URL.length() - 1 : HandlePidProvider.HTTP_HDL_RESOLVER_URL.length() - 1; index2 = identifierString.indexOf("/", index1 + 1); - } else if (identifierString.startsWith(DOIServiceBean.DOI_RESOLVER_URL) || identifierString.startsWith(DOIServiceBean.HTTP_DOI_RESOLVER_URL) || identifierString.startsWith(DOIServiceBean.DXDOI_RESOLVER_URL) || identifierString.startsWith(DOIServiceBean.HTTP_DXDOI_RESOLVER_URL)) { + } else if (identifierString.startsWith(DOIProvider.DOI_RESOLVER_URL) || identifierString.startsWith(DOIProvider.HTTP_DOI_RESOLVER_URL) || identifierString.startsWith(DOIProvider.DXDOI_RESOLVER_URL) || identifierString.startsWith(DOIProvider.HTTP_DXDOI_RESOLVER_URL)) { logger.fine("Processing DOI identifier formatted as a resolver URL: "+identifierString); - protocol = DOIServiceBean.DOI_PROTOCOL; - identifierString = identifierString.replace(DOIServiceBean.DXDOI_RESOLVER_URL, DOIServiceBean.DOI_RESOLVER_URL); - identifierString = identifierString.replace(DOIServiceBean.HTTP_DXDOI_RESOLVER_URL, DOIServiceBean.HTTP_DOI_RESOLVER_URL); - index1 = (identifierString.startsWith(DOIServiceBean.DOI_RESOLVER_URL)) ? DOIServiceBean.DOI_RESOLVER_URL.length() - 1 : DOIServiceBean.HTTP_DOI_RESOLVER_URL.length() - 1; + protocol = DOIProvider.DOI_PROTOCOL; + identifierString = identifierString.replace(DOIProvider.DXDOI_RESOLVER_URL, DOIProvider.DOI_RESOLVER_URL); + identifierString = identifierString.replace(DOIProvider.HTTP_DXDOI_RESOLVER_URL, DOIProvider.HTTP_DOI_RESOLVER_URL); + index1 = (identifierString.startsWith(DOIProvider.DOI_RESOLVER_URL)) ? DOIProvider.DOI_RESOLVER_URL.length() - 1 : DOIProvider.HTTP_DOI_RESOLVER_URL.length() - 1; index2 = identifierString.indexOf("/", index1 + 1); - } else if (identifierString.startsWith(PermaLinkPidProviderServiceBean.PERMA_RESOLVER_URL + Dataset.TARGET_URL)) { - protocol = PermaLinkPidProviderServiceBean.PERMA_PROTOCOL; - index1 = PermaLinkPidProviderServiceBean.PERMA_RESOLVER_URL.length() + + Dataset.TARGET_URL.length() - 1; + } else if (identifierString.startsWith(PermaLinkPidProvider.PERMA_RESOLVER_URL + Dataset.TARGET_URL)) { + protocol = PermaLinkPidProvider.PERMA_PROTOCOL; + index1 = PermaLinkPidProvider.PERMA_RESOLVER_URL.length() + + Dataset.TARGET_URL.length() - 1; index2 = identifierString.indexOf("/", index1 + 1); } else { logger.warning("HTTP Url in supplied as the identifier is neither a Handle nor DOI resolver: "+identifierString); diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java index ba34a3d1ed1..4f565f70d9e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java @@ -33,6 +33,7 @@ import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.impl.UpdateDatasetVersionCommand; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.FileUtil; @@ -58,7 +59,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import jakarta.servlet.http.HttpServletRequest; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; @Named @Dependent @@ -360,7 +360,7 @@ private DataFile createPackageDataFile(List files) { if (commandEngine.getContext().systemConfig().isFilePIDsEnabledForCollection(dataset.getOwner())) { - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(packageFile.getProtocol(), commandEngine.getContext()); + PidProvider idServiceBean = PidProvider.getBean(packageFile.getProtocol(), commandEngine.getContext()); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { packageFile.setIdentifier(idServiceBean.generateDataFileIdentifier(packageFile)); } @@ -376,7 +376,7 @@ private DataFile createPackageDataFile(List files) { if (!packageFile.isIdentifierRegistered()) { String doiRetString = ""; - idServiceBean = GlobalIdServiceBean.getBean(commandEngine.getContext()); + idServiceBean = PidProvider.getBean(commandEngine.getContext()); try { doiRetString = idServiceBean.createIdentifier(packageFile); } catch (Throwable e) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java index f74c1222bb0..397bbb333bc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java @@ -1,8 +1,5 @@ package edu.harvard.iq.dataverse.engine.command; -import edu.harvard.iq.dataverse.DOIDataCiteServiceBean; -import edu.harvard.iq.dataverse.DOIEZIdServiceBean; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.DataFileServiceBean; import edu.harvard.iq.dataverse.DatasetLinkingServiceBean; import edu.harvard.iq.dataverse.DatasetServiceBean; @@ -32,8 +29,11 @@ import edu.harvard.iq.dataverse.datacapturemodule.DataCaptureModuleServiceBean; import edu.harvard.iq.dataverse.engine.DataverseEngine; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.FakePidProviderServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.SolrIndexServiceBean; @@ -100,15 +100,15 @@ public interface CommandContext { public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels(); - public DOIEZIdServiceBean doiEZId(); + public DOIEZIdProvider doiEZId(); - public DOIDataCiteServiceBean doiDataCite(); + public DataCiteDOIProvider doiDataCite(); - public FakePidProviderServiceBean fakePidProvider(); + public FakeDOIProvider fakePidProvider(); - public HandlenetServiceBean handleNet(); + public HandlePidProvider handleNet(); - public PermaLinkPidProviderServiceBean permaLinkProvider(); + public PermaLinkPidProvider permaLinkProvider(); public GuestbookServiceBean guestbooks(); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index 303d8e1c25f..f847b7e6243 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -12,6 +12,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import static edu.harvard.iq.dataverse.util.StringUtil.isEmpty; import java.io.IOException; @@ -81,7 +82,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { additionalParameterTests(ctxt); Dataset theDataset = getDataset(); - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(ctxt); + PidProvider idServiceBean = PidProvider.getBean(ctxt); if ( isEmpty(theDataset.getIdentifier()) ) { theDataset.setIdentifier(idServiceBean.generateDatasetIdentifier(theDataset)); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java index 6061461306d..fea3bd3387e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java @@ -13,6 +13,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.util.BundleUtil; import java.sql.Timestamp; @@ -23,7 +24,6 @@ import static java.util.stream.Collectors.joining; import jakarta.validation.ConstraintViolation; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.MetadataBlock; import edu.harvard.iq.dataverse.TermsOfUseAndAccess; import edu.harvard.iq.dataverse.settings.JvmSettings; @@ -152,7 +152,7 @@ protected void validateOrDie(DatasetVersion dsv, Boolean lenient) throws Command */ protected void registerExternalIdentifier(Dataset theDataset, CommandContext ctxt, boolean retry) throws CommandException { if (!theDataset.isIdentifierRegistered()) { - GlobalIdServiceBean globalIdServiceBean = GlobalIdServiceBean.getBean(theDataset.getProtocol(), ctxt); + PidProvider globalIdServiceBean = PidProvider.getBean(theDataset.getProtocol(), ctxt); if ( globalIdServiceBean != null ) { try { if (globalIdServiceBean.alreadyRegistered(theDataset)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java index b988fd05f03..4eeb36ed254 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java @@ -1,6 +1,5 @@ package edu.harvard.iq.dataverse.engine.command.impl; -import edu.harvard.iq.dataverse.DOIDataCiteRegisterService; import edu.harvard.iq.dataverse.DataCitation; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; @@ -14,6 +13,7 @@ import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; +import edu.harvard.iq.dataverse.pidproviders.datacite.DOIDataCiteRegisterService; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.bagit.BagGenerator; import edu.harvard.iq.dataverse.util.bagit.OREMap; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java index c9ebe735e31..4b5d46f94e3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java @@ -12,12 +12,12 @@ import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import static edu.harvard.iq.dataverse.util.StringUtil.nonEmpty; import java.util.logging.Logger; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import java.util.List; import java.sql.Timestamp; @@ -72,7 +72,7 @@ public CreateNewDatasetCommand(Dataset theDataset, DataverseRequest aRequest, Te @Override protected void additionalParameterTests(CommandContext ctxt) throws CommandException { if ( nonEmpty(getDataset().getIdentifier()) ) { - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(getDataset().getProtocol(), ctxt); + PidProvider idServiceBean = PidProvider.getBean(getDataset().getProtocol(), ctxt); if ( !idServiceBean.isGlobalIdUnique(getDataset().getGlobalId()) ) { throw new IllegalCommandException(String.format("Dataset with identifier '%s', protocol '%s' and authority '%s' already exists", getDataset().getIdentifier(), getDataset().getProtocol(), getDataset().getAuthority()), @@ -88,7 +88,7 @@ protected DatasetVersion getVersionToPersist( Dataset theDataset ) { @Override protected void handlePid(Dataset theDataset, CommandContext ctxt) throws CommandException { - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(ctxt); + PidProvider idServiceBean = PidProvider.getBean(ctxt); if(!idServiceBean.isConfigured()) { throw new IllegalCommandException("PID Provider " + idServiceBean.getProviderInformation().get(0) + " is not configured.", this); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java index e2730ec06d3..997a2d365b1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.util.FileUtil; import edu.harvard.iq.dataverse.util.StringUtil; import java.io.IOException; @@ -23,7 +24,6 @@ import java.util.Collections; import java.util.logging.Level; import java.util.logging.Logger; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; /** * Deletes a data file, both DB entity and filesystem object. @@ -202,7 +202,7 @@ public FileVisitResult postVisitDirectory(final Path dir, final IOException e) */ } } - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(ctxt); + PidProvider idServiceBean = PidProvider.getBean(ctxt); try { if (idServiceBean.alreadyRegistered(doomed)) { idServiceBean.deleteIdentifier(doomed); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java index 274aeb3c3fd..92c42b1ce49 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java @@ -1,7 +1,6 @@ package edu.harvard.iq.dataverse.engine.command.impl; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand; @@ -11,6 +10,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import org.apache.commons.httpclient.HttpException; @@ -44,7 +44,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { String nonNullDefaultIfKeyNotFound = ""; String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(protocol, ctxt); + PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); try { idServiceBean.deleteIdentifier(dataset); // Success! Clear the create time, etc. diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java index 41093444360..1966743340c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java @@ -15,6 +15,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.search.IndexResponse; import java.util.ArrayList; import java.util.Collections; @@ -22,7 +23,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; + import edu.harvard.iq.dataverse.batch.util.LoggingUtil; import java.io.IOException; import java.util.concurrent.Future; @@ -99,7 +100,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { } if (!doomed.isHarvested()) { - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(ctxt); + PidProvider idServiceBean = PidProvider.getBean(ctxt); try { if (idServiceBean.alreadyRegistered(doomed)) { idServiceBean.deleteIdentifier(doomed); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java index 89cfc732455..0566c9e3fb6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java @@ -20,6 +20,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.export.ExportService; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; @@ -30,7 +31,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; + import edu.harvard.iq.dataverse.batch.util.LoggingUtil; import edu.harvard.iq.dataverse.dataaccess.StorageIO; import edu.harvard.iq.dataverse.engine.command.Command; @@ -386,7 +387,7 @@ private void validateDataFiles(Dataset dataset, CommandContext ctxt) throws Comm private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) throws CommandException { String protocol = getDataset().getProtocol(); String authority = getDataset().getAuthority(); - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(protocol, ctxt); + PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); if (idServiceBean != null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GrantSuperuserStatusCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GrantSuperuserStatusCommand.java index 42af43b7247..ec8c8976260 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GrantSuperuserStatusCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GrantSuperuserStatusCommand.java @@ -14,7 +14,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; /** * diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java index 478272950bd..55d7f44ccb9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java @@ -1,14 +1,14 @@ package edu.harvard.iq.dataverse.engine.command.impl; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.engine.command.CommandContext; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; -import edu.harvard.iq.dataverse.pidproviders.FakePidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import java.io.IOException; import java.util.Collections; @@ -80,7 +80,7 @@ protected void additionalParameterTests(CommandContext ctxt) throws CommandExcep * Dataverse) but aren't findable to be used. That could be the case if, for * example, someone was importing a draft dataset from elsewhere. */ - GlobalIdServiceBean globalIdServiceBean = GlobalIdServiceBean.getBean(ds.getProtocol(), ctxt); + PidProvider globalIdServiceBean = PidProvider.getBean(ds.getProtocol(), ctxt); if (globalIdServiceBean != null) { if (globalIdServiceBean.alreadyRegistered(ds.getGlobalId(), true)) { return; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java index f5ef121dee2..18c7d05cf1b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java @@ -2,7 +2,6 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetLock; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.engine.command.Command; @@ -11,6 +10,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java index 779bc7fb7fe..27ca856580b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java @@ -10,11 +10,12 @@ import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import java.sql.Timestamp; import java.util.Date; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; -import edu.harvard.iq.dataverse.HandlenetServiceBean; + import edu.harvard.iq.dataverse.batch.util.LoggingUtil; import java.io.IOException; import org.apache.solr.client.solrj.SolrServerException; @@ -52,7 +53,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); String authority = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); // Get the idServiceBean that is configured to mint new IDs - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(protocol, ctxt); + PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); try { //Test to see if identifier already present //if so, leave. @@ -77,7 +78,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { if (doiRetString != null && doiRetString.contains(target.getIdentifier())) { if (!idServiceBean.registerWhenPublished()) { // Should register ID before publicize() is called - // For example, DOIEZIdServiceBean tries to recreate the id if the identifier isn't registered before + // For example, DOIEZIdProvider tries to recreate the id if the identifier isn't registered before // publicizeIdentifier is called target.setIdentifierRegistered(true); target.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); @@ -107,7 +108,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { if (doiRetString != null && doiRetString.contains(df.getIdentifier())) { if (!idServiceBean.registerWhenPublished()) { // Should register ID before publicize() is called - // For example, DOIEZIdServiceBean tries to recreate the id if the identifier isn't registered before + // For example, DOIEZIdProvider tries to recreate the id if the identifier isn't registered before // publicizeIdentifier is called df.setIdentifierRegistered(true); df.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); @@ -145,7 +146,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { private Boolean processMigrateHandle (CommandContext ctxt){ boolean retval = true; if(!target.isInstanceofDataset()) return false; - if(!target.getProtocol().equals(HandlenetServiceBean.HDL_PROTOCOL)) return false; + if(!target.getProtocol().equals(HandlePidProvider.HDL_PROTOCOL)) return false; AlternativePersistentIdentifier api = new AlternativePersistentIdentifier(); api.setProtocol(target.getProtocol()); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java index 6b2872f3397..a956cce45d4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java @@ -1,7 +1,6 @@ package edu.harvard.iq.dataverse.engine.command.impl; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand; @@ -11,6 +10,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import java.util.Arrays; @@ -43,7 +43,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { String nonNullDefaultIfKeyNotFound = ""; String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(protocol, ctxt); + PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); try { String returnString = idServiceBean.createIdentifier(dataset); logger.fine(returnString); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RevokeSuperuserStatusCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RevokeSuperuserStatusCommand.java index 0abb53ea4fb..7e55102ef5f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RevokeSuperuserStatusCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RevokeSuperuserStatusCommand.java @@ -14,7 +14,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; /** * diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java index 1f5989c9e08..8c272d11f15 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java @@ -10,10 +10,11 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; + import java.sql.Timestamp; import java.util.Collections; import java.util.Date; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; /** * @@ -36,7 +37,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { throw new PermissionException("Update Target URL can only be called by superusers.", this, Collections.singleton(Permission.EditDataset), target); } - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(target.getProtocol(), ctxt); + PidProvider idServiceBean = PidProvider.getBean(target.getProtocol(), ctxt); try { String doiRetString = idServiceBean.modifyIdentifierTargetURL(target); if (doiRetString != null && doiRetString.contains(target.getIdentifier())) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java index 7230f9f9c0a..78c9a6e4a83 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java @@ -2,7 +2,6 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand; @@ -11,6 +10,7 @@ import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import java.sql.Timestamp; @@ -46,7 +46,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { //the single dataset update api checks for drafts before calling the command return; } - GlobalIdServiceBean idServiceBean = GlobalIdServiceBean.getBean(target.getProtocol(), ctxt); + PidProvider idServiceBean = PidProvider.getBean(target.getProtocol(), ctxt); try { Boolean doiRetString = idServiceBean.publicizeIdentifier(target); if (doiRetString) { diff --git a/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java b/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java index a7967f6ccb6..9edb456c890 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java @@ -8,12 +8,11 @@ import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; - -import edu.harvard.iq.dataverse.DOIDataCiteRegisterService; import edu.harvard.iq.dataverse.DataCitation; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; +import edu.harvard.iq.dataverse.pidproviders.datacite.DOIDataCiteRegisterService; import io.gdcc.spi.export.ExportDataProvider; import edu.harvard.iq.dataverse.util.bagit.OREMap; import edu.harvard.iq.dataverse.util.json.JsonPrinter; diff --git a/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java b/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java index 7b0a92a4372..6cc4210e6a9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java @@ -13,15 +13,15 @@ import com.google.gson.Gson; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DatasetFieldConstant; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.api.dto.DatasetDTO; import edu.harvard.iq.dataverse.api.dto.DatasetVersionDTO; import edu.harvard.iq.dataverse.api.dto.FieldDTO; import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO; import edu.harvard.iq.dataverse.util.PersonOrOrgUtil; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.util.json.JsonUtil; import java.util.regex.Matcher; @@ -189,10 +189,10 @@ public static void writeIdentifierElement(XMLStreamWriter xmlw, String identifie if (StringUtils.isNotBlank(identifier)) { Map identifier_map = new HashMap(); - if (StringUtils.containsIgnoreCase(identifier, DOIServiceBean.DOI_RESOLVER_URL)) { + if (StringUtils.containsIgnoreCase(identifier, DOIProvider.DOI_RESOLVER_URL)) { identifier_map.put("identifierType", "DOI"); identifier = StringUtils.substring(identifier, identifier.indexOf("10.")); - } else if (StringUtils.containsIgnoreCase(identifier, HandlenetServiceBean.HDL_RESOLVER_URL)) { + } else if (StringUtils.containsIgnoreCase(identifier, HandlePidProvider.HDL_RESOLVER_URL)) { identifier_map.put("identifierType", "Handle"); if (StringUtils.contains(identifier, "http")) { identifier = identifier.replace(identifier.substring(0, identifier.indexOf("/") + 2), ""); diff --git a/src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java similarity index 96% rename from src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 7312df5ec17..c0da9eafea8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/AbstractGlobalIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -1,5 +1,14 @@ -package edu.harvard.iq.dataverse; - +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetAuthor; +import edu.harvard.iq.dataverse.DatasetField; +import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.DvObjectServiceBean; +import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.datacite.Util; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; import java.io.InputStream; @@ -15,9 +24,9 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -public abstract class AbstractGlobalIdServiceBean implements GlobalIdServiceBean { +public abstract class AbstractPidProvider implements PidProvider { - private static final Logger logger = Logger.getLogger(AbstractGlobalIdServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(AbstractPidProvider.class.getCanonicalName()); @Inject DataverseServiceBean dataverseService; @@ -252,12 +261,12 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { // before and after it // Strip any whitespace, ; and ' from authority (should finding them cause a // failure instead?) - authority = GlobalIdServiceBean.formatIdentifierString(identifierString.substring(0, index)); - if (GlobalIdServiceBean.testforNullTerminator(authority)) { + authority = PidProvider.formatIdentifierString(identifierString.substring(0, index)); + if (PidProvider.testforNullTerminator(authority)) { return null; } - identifier = GlobalIdServiceBean.formatIdentifierString(identifierString.substring(index + 1)); - if (GlobalIdServiceBean.testforNullTerminator(identifier)) { + identifier = PidProvider.formatIdentifierString(identifierString.substring(index + 1)); + if (PidProvider.testforNullTerminator(identifier)) { return null; } } else { @@ -273,7 +282,7 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden return null; } logger.fine("Parsing: " + protocol + ":" + authority + getSeparator() + identifier + " in " + getProviderInformation().get(0)); - if(!GlobalIdServiceBean.isValidGlobalId(protocol, authority, identifier)) { + if(!PidProvider.isValidGlobalId(protocol, authority, identifier)) { return null; } return new GlobalId(protocol, authority, identifier, getSeparator(), getUrlPrefix(), @@ -383,7 +392,7 @@ private String generateIdentifierFromStoredProcedureDependent(DataFile datafile, } - class GlobalIdMetadataTemplate { + public class GlobalIdMetadataTemplate { private String template; diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIEZIdProvider.java similarity index 95% rename from src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIEZIdProvider.java index af2a1d60be1..76c5c7f4450 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIEZIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIEZIdProvider.java @@ -1,5 +1,9 @@ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders; +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.ucsb.nceas.ezid.EZIDException; import edu.ucsb.nceas.ezid.EZIDService; @@ -13,10 +17,9 @@ * * @author skraffmiller */ -@Stateless -public class DOIEZIdServiceBean extends DOIServiceBean { +public class DOIEZIdProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(DOIEZIdServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(DOIEZIdProvider.class.getCanonicalName()); EZIDService ezidService; @@ -25,7 +28,7 @@ public class DOIEZIdServiceBean extends DOIServiceBean { // This has a sane default in microprofile-config.properties private final String baseUrl = JvmSettings.EZID_API_URL.lookup("ezid"); - public DOIEZIdServiceBean() { + public DOIEZIdProvider() { // Creating the service doesn't do any harm, just initializing some object data here. // Makes sure we don't run into NPEs from the other methods, but will obviously fail if the // login below does not work. @@ -281,5 +284,16 @@ protected String getProviderKeyName() { return "EZID"; } + @Override + public String getProviderType() { + return TYPE; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java similarity index 87% rename from src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java index 56131872100..1b1ed094613 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java @@ -1,8 +1,9 @@ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; -public abstract class DOIServiceBean extends AbstractGlobalIdServiceBean { +public abstract class DOIProvider extends AbstractPidProvider { public static final String DOI_PROTOCOL = "doi"; public static final String DOI_RESOLVER_URL = "https://doi.org/"; @@ -10,7 +11,7 @@ public abstract class DOIServiceBean extends AbstractGlobalIdServiceBean { public static final String DXDOI_RESOLVER_URL = "https://dx.doi.org/"; public static final String HTTP_DXDOI_RESOLVER_URL = "http://dx.doi.org/"; - public DOIServiceBean() { + public DOIProvider() { super(); } @@ -36,7 +37,7 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { return null; } GlobalId globalId = super.parsePersistentId(protocol, identifierString); - if (globalId!=null && !GlobalIdServiceBean.checkDOIAuthority(globalId.getAuthority())) { + if (globalId!=null && !PidProvider.checkDOIAuthority(globalId.getAuthority())) { return null; } return globalId; diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java similarity index 93% rename from src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index 72aab51fc19..1314af74c50 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -1,4 +1,4 @@ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders; import java.io.IOException; import java.net.HttpURLConnection; @@ -12,7 +12,10 @@ import jakarta.ejb.EJB; import jakarta.ejb.Stateless; - +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.datacite.DOIDataCiteRegisterService; import edu.harvard.iq.dataverse.settings.JvmSettings; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; @@ -22,10 +25,9 @@ * * @author luopc */ -@Stateless -public class DOIDataCiteServiceBean extends DOIServiceBean { +public class DataCiteDOIProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(DOIDataCiteServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(DataCiteDOIProvider.class.getCanonicalName()); private static final String PUBLIC = "public"; private static final String FINDABLE = "findable"; @@ -247,4 +249,20 @@ public List getProviderInformation(){ protected String getProviderKeyName() { return "DataCite"; } + + + + @Override + public String getProviderType() { + // TODO Auto-generated method stub + return null; + } + + + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index 08d51815d2e..d1be90bda6d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -1,14 +1,12 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.DOIDataCiteServiceBean; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.settings.JvmSettings; class DataCiteProviderFactory extends PidProviderFactory { - public GlobalIdServiceBean createProvider(String providerName) { + public PidProvider createProvider(String providerName) { String providerType=JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); - if(!providerType.equals(DOIDataCiteServiceBean.TYPE)) { + if(!providerType.equals(DataCiteDOIProvider.TYPE)) { //Being asked to create a non-DataCite provider return null; } @@ -20,10 +18,10 @@ public GlobalIdServiceBean createProvider(String providerName) { String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); String[] whitelist = JvmSettings.PID_PROVIDER_WHITELIST.lookup(providerName).split(","); - return new DOIDataCiteServiceBean(providerAuthority, providerShoulder, mdsUrl, apiUrl, username, password); + return new DataCiteDOIProvider(providerAuthority, providerShoulder, mdsUrl, apiUrl, username, password); } public String getType() { - return DOIDataCiteServiceBean.TYPE; + return DataCiteDOIProvider.TYPE; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java similarity index 82% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java index 3bd9d9dd022..86ad5b567fc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java @@ -1,6 +1,5 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; @@ -11,10 +10,9 @@ import jakarta.ejb.Stateless; -@Stateless -public class FakePidProviderServiceBean extends DOIServiceBean { +public class FakeDOIProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(FakePidProviderServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(FakeDOIProvider.class.getCanonicalName()); //Only need to check locally @@ -74,4 +72,16 @@ protected String getProviderKeyName() { return "FAKE"; } + @Override + public String getProviderType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java similarity index 95% rename from src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index 767a099a001..f8fbd797604 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -18,8 +18,12 @@ Version 3.0. */ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; @@ -60,21 +64,20 @@ * As of now, it only does the registration updates, to accommodate * the modifyRegistration datasets API sub-command. */ -@Stateless -public class HandlenetServiceBean extends AbstractGlobalIdServiceBean { +public class HandlePidProvider extends AbstractPidProvider { @EJB DataverseServiceBean dataverseService; @EJB SettingsServiceBean settingsService; - private static final Logger logger = Logger.getLogger(HandlenetServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(HandlePidProvider.class.getCanonicalName()); public static final String HDL_PROTOCOL = "hdl"; int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); public static final String HTTP_HDL_RESOLVER_URL = "http://hdl.handle.net/"; public static final String HDL_RESOLVER_URL = "https://hdl.handle.net/"; - public HandlenetServiceBean() { + public HandlePidProvider() { logger.log(Level.FINE,"Constructor"); configured = true; } @@ -438,6 +441,24 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden public String getUrlPrefix() { return HDL_RESOLVER_URL; } + + @Override + public String getProtocol() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getProviderType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java similarity index 90% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 2d0539bcfa3..36a0b994ce3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProviderServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -1,9 +1,7 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.AbstractGlobalIdServiceBean; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; import edu.harvard.iq.dataverse.util.SystemConfig; @@ -26,10 +24,9 @@ * This will be overridable by a configurable parameter to support use of an external resolver. * */ -@Stateless -public class PermaLinkPidProviderServiceBean extends AbstractGlobalIdServiceBean { +public class PermaLinkPidProvider extends AbstractPidProvider { - private static final Logger logger = Logger.getLogger(PermaLinkPidProviderServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(PermaLinkPidProvider.class.getCanonicalName()); public static final String PERMA_PROTOCOL = "perma"; public static final String PERMA_PROVIDER_NAME = "PERMA"; @@ -137,8 +134,8 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { identifier = identifierString.substring(authority.length()); } } - identifier = GlobalIdServiceBean.formatIdentifierString(identifier); - if (GlobalIdServiceBean.testforNullTerminator(identifier)) { + identifier = PidProvider.formatIdentifierString(identifier); + if (PidProvider.testforNullTerminator(identifier)) { return null; } return new GlobalId(PERMA_PROTOCOL, authority, identifier, separator, getUrlPrefix(), PERMA_PROVIDER_NAME); @@ -157,4 +154,25 @@ public String getUrlPrefix() { return PERMA_RESOLVER_URL + "/citation?persistentId=" + PERMA_PROTOCOL + ":"; } + + + @Override + public String getProtocol() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public String getProviderType() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java similarity index 84% rename from src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index 06438dfb27d..22ee330f855 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GlobalIdServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -1,19 +1,22 @@ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders; -import static edu.harvard.iq.dataverse.GlobalIdServiceBean.logger; +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.engine.command.CommandContext; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; +import static edu.harvard.iq.dataverse.pidproviders.PidProvider.logger; + import java.util.*; import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; -public interface GlobalIdServiceBean { +public interface PidProvider { - static final Logger logger = Logger.getLogger(GlobalIdServiceBean.class.getCanonicalName()); + static final Logger logger = Logger.getLogger(PidProvider.class.getCanonicalName()); boolean alreadyRegistered(DvObject dvo) throws Exception; @@ -71,10 +74,10 @@ public interface GlobalIdServiceBean { //ToDo - now need to get the correct provider based on the protocol, authority, and shoulder (for new pids)/indentifier (for existing pids) - static GlobalIdServiceBean getBean(String protocol, CommandContext ctxt) { - final Function protocolHandler = BeanDispatcher.DISPATCHER.get(protocol); + static PidProvider getBean(String protocol, CommandContext ctxt) { + final Function protocolHandler = BeanDispatcher.DISPATCHER.get(protocol); if ( protocolHandler != null ) { - GlobalIdServiceBean theBean = protocolHandler.apply(ctxt); + PidProvider theBean = protocolHandler.apply(ctxt); if(theBean != null && theBean.isConfigured()) { logger.fine("getBean returns " + theBean.getProviderInformation().get(0) + " for protocol " + protocol); } @@ -85,7 +88,7 @@ static GlobalIdServiceBean getBean(String protocol, CommandContext ctxt) { } } - static GlobalIdServiceBean getBean(CommandContext ctxt) { + static PidProvider getBean(CommandContext ctxt) { return getBean(ctxt.settings().getValueForKey(Key.Protocol, ""), ctxt); } @@ -126,16 +129,16 @@ public static boolean isValidGlobalId(String protocol, String authority, String if (protocol == null || authority == null || identifier == null) { return false; } - if(!authority.equals(GlobalIdServiceBean.formatIdentifierString(authority))) { + if(!authority.equals(PidProvider.formatIdentifierString(authority))) { return false; } - if (GlobalIdServiceBean.testforNullTerminator(authority)) { + if (PidProvider.testforNullTerminator(authority)) { return false; } - if(!identifier.equals(GlobalIdServiceBean.formatIdentifierString(identifier))) { + if(!identifier.equals(PidProvider.formatIdentifierString(identifier))) { return false; } - if (GlobalIdServiceBean.testforNullTerminator(identifier)) { + if (PidProvider.testforNullTerminator(identifier)) { return false; } return true; @@ -204,7 +207,7 @@ static boolean checkDOIAuthority(String doiAuthority){ */ // FWIW: For lists of PIDs not managed by the provider covered by authority/shoulder, we need a way to add them to one provider and exlude them if another registered provider handles their authority/shoulder (probably rare?) class BeanDispatcher { - static final Map> DISPATCHER = new HashMap<>(); + static final Map> DISPATCHER = new HashMap<>(); static { DISPATCHER.put("hdl", ctxt->ctxt.handleNet() ); @@ -220,6 +223,6 @@ class BeanDispatcher { } }); - DISPATCHER.put(PermaLinkPidProviderServiceBean.PERMA_PROTOCOL, ctxt->ctxt.permaLinkProvider() ); + DISPATCHER.put(PermaLinkPidProvider.PERMA_PROTOCOL, ctxt->ctxt.permaLinkProvider() ); } } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java index dc2e34d7abd..c7bc1be02c9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java @@ -1,11 +1,9 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; - public interface PidProviderFactory { public String getType(); - public GlobalIdServiceBean createPidProvider(String name); + public PidProvider createPidProvider(String name); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index f14f5318034..47a7f08e41e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -24,11 +24,6 @@ import jakarta.ejb.EJB; import jakarta.ejb.Singleton; import jakarta.ejb.Startup; - -import edu.harvard.iq.dataverse.DOIDataCiteServiceBean; -import edu.harvard.iq.dataverse.DOIEZIdServiceBean; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.export.ExportService; import edu.harvard.iq.dataverse.settings.JvmSettings; import io.gdcc.spi.export.Exporter; @@ -107,7 +102,7 @@ private void loadProviders() { for (String name : providers) { String type = JvmSettings.PID_PROVIDER_TYPE.lookup(name); if (pidProviderFactoryMap.containsKey(type)) { - GlobalIdServiceBean provider = pidProviderFactoryMap.get(type).createPidProvider(name); + PidProvider provider = pidProviderFactoryMap.get(type).createPidProvider(name); PidUtil.addToProviderList(provider); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index b67b462616d..41a35c1fe7c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -1,9 +1,6 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import java.io.IOException; import java.io.InputStream; @@ -113,21 +110,21 @@ public static JsonObjectBuilder queryDoi(GlobalId globalId, String baseUrl, Stri * @return DOI in the form 10.7910/DVN/TJCLKP (no "doi:") */ private static String acceptOnlyDoi(GlobalId globalId) { - if (!DOIServiceBean.DOI_PROTOCOL.equals(globalId.getProtocol())) { + if (!DOIProvider.DOI_PROTOCOL.equals(globalId.getProtocol())) { throw new IllegalArgumentException(BundleUtil.getStringFromBundle("pids.datacite.errors.DoiOnly")); } return globalId.getAuthority() + "/" + globalId.getIdentifier(); } - static Map providerMap = new HashMap(); - static Map unmanagedProviderMap = new HashMap(); + static Map providerMap = new HashMap(); + static Map unmanagedProviderMap = new HashMap(); - public static void addToProviderList(GlobalIdServiceBean pidProvider) { + public static void addToProviderList(PidProvider pidProvider) { providerMap.put(pidProvider.getName(), pidProvider); } - public static void addAllToUnmanagedProviderList(List list) { - for (GlobalIdServiceBean pidProvider : list) { + public static void addAllToUnmanagedProviderList(List list) { + for (PidProvider pidProvider : list) { unmanagedProviderMap.put(pidProvider.getProviderInformation().get(0), pidProvider); } } @@ -139,7 +136,7 @@ public static void addAllToUnmanagedProviderList(List list) */ public static GlobalId parseAsGlobalID(String identifier) { logger.fine("In parseAsGlobalId: " + providerMap.size()); - for (GlobalIdServiceBean pidProvider : providerMap.values()) { + for (PidProvider pidProvider : providerMap.values()) { logger.fine(" Checking " + String.join(",", pidProvider.getProviderInformation())); GlobalId globalId = pidProvider.parsePersistentId(identifier); if (globalId != null) { @@ -147,7 +144,7 @@ public static GlobalId parseAsGlobalID(String identifier) { } } // If no providers can managed this PID, at least allow it to be recognized - for (GlobalIdServiceBean pidProvider : unmanagedProviderMap.values()) { + for (PidProvider pidProvider : unmanagedProviderMap.values()) { logger.fine(" Checking " + String.join(",", pidProvider.getProviderInformation())); GlobalId globalId = pidProvider.parsePersistentId(identifier); if (globalId != null) { @@ -165,14 +162,14 @@ public static GlobalId parseAsGlobalID(String identifier) { public static GlobalId parseAsGlobalID(String protocol, String authority, String identifier) { logger.fine("Looking for " + protocol + " " + authority + " " + identifier); logger.fine("In parseAsGlobalId: " + providerMap.size()); - for (GlobalIdServiceBean pidProvider : providerMap.values()) { + for (PidProvider pidProvider : providerMap.values()) { logger.fine(" Checking " + String.join(",", pidProvider.getProviderInformation())); GlobalId globalId = pidProvider.parsePersistentId(protocol, authority, identifier); if (globalId != null) { return globalId; } } - for (GlobalIdServiceBean pidProvider : unmanagedProviderMap.values()) { + for (PidProvider pidProvider : unmanagedProviderMap.values()) { logger.fine(" Checking " + String.join(",", pidProvider.getProviderInformation())); GlobalId globalId = pidProvider.parsePersistentId(protocol, authority, identifier); if (globalId != null) { @@ -189,26 +186,26 @@ public static GlobalId parseAsGlobalID(String protocol, String authority, String * This method should be deprecated/removed when further refactoring to support * multiple PID providers is done. At that point, when the providers aren't * beans, this code can be moved into other classes that go in the providerMap. - * If this method is not kept in sync with the DOIServiceBean and - * HandlenetServiceBean implementations, the tests using it won't be valid tests + * If this method is not kept in sync with the DOIProvider and + * HandlePidProvider implementations, the tests using it won't be valid tests * of the production code. */ private static GlobalId parseUnmanagedDoiOrHandle(String protocol, String authority, String identifier) { // Default recognition - could be moved to new classes in the future. - if (!GlobalIdServiceBean.isValidGlobalId(protocol, authority, identifier)) { + if (!PidProvider.isValidGlobalId(protocol, authority, identifier)) { return null; } String urlPrefix = null; switch (protocol) { - case DOIServiceBean.DOI_PROTOCOL: - if (!GlobalIdServiceBean.checkDOIAuthority(authority)) { + case DOIProvider.DOI_PROTOCOL: + if (!PidProvider.checkDOIAuthority(authority)) { return null; } - urlPrefix = DOIServiceBean.DOI_RESOLVER_URL; + urlPrefix = DOIProvider.DOI_RESOLVER_URL; break; - case HandlenetServiceBean.HDL_PROTOCOL: - urlPrefix = HandlenetServiceBean.HDL_RESOLVER_URL; + case HandlePidProvider.HDL_PROTOCOL: + urlPrefix = HandlePidProvider.HDL_RESOLVER_URL; break; } return new GlobalId(protocol, authority, identifier, "/", urlPrefix, null); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java similarity index 84% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index f7e9372cc9b..cc9cc237848 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -11,7 +11,6 @@ import org.apache.commons.httpclient.HttpException; import org.apache.commons.lang3.NotImplementedException; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; @@ -20,10 +19,9 @@ * */ -@Stateless -public class UnmanagedDOIServiceBean extends DOIServiceBean { +public class UnmanagedDOIProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(UnmanagedDOIServiceBean.class.getCanonicalName()); + private static final Logger logger = Logger.getLogger(UnmanagedDOIProvider.class.getCanonicalName()); @PostConstruct private void init() { @@ -76,8 +74,20 @@ public List getProviderInformation() { return List.of("UnmanagedDOIProvider", ""); } + @Override + public String getProviderType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + // PID recognition - // Done by DOIServiceBean + // Done by DOIProvider } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java index c856c5363e0..245cc11f4cd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java @@ -1,9 +1,8 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.AbstractGlobalIdServiceBean; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.HandlenetServiceBean; + import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -15,7 +14,7 @@ * */ @Stateless -public class UnmanagedHandlenetServiceBean extends AbstractGlobalIdServiceBean { +public class UnmanagedHandlenetServiceBean extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedHandlenetServiceBean.class.getCanonicalName()); @@ -71,19 +70,19 @@ public boolean publicizeIdentifier(DvObject dvObject) { @Override public GlobalId parsePersistentId(String pidString) { - if (pidString.startsWith(HandlenetServiceBean.HDL_RESOLVER_URL)) { - pidString = pidString.replace(HandlenetServiceBean.HDL_RESOLVER_URL, - (HandlenetServiceBean.HDL_PROTOCOL + ":")); - } else if (pidString.startsWith(HandlenetServiceBean.HTTP_HDL_RESOLVER_URL)) { - pidString = pidString.replace(HandlenetServiceBean.HTTP_HDL_RESOLVER_URL, - (HandlenetServiceBean.HDL_PROTOCOL + ":")); + if (pidString.startsWith(HandlePidProvider.HDL_RESOLVER_URL)) { + pidString = pidString.replace(HandlePidProvider.HDL_RESOLVER_URL, + (HandlePidProvider.HDL_PROTOCOL + ":")); + } else if (pidString.startsWith(HandlePidProvider.HTTP_HDL_RESOLVER_URL)) { + pidString = pidString.replace(HandlePidProvider.HTTP_HDL_RESOLVER_URL, + (HandlePidProvider.HDL_PROTOCOL + ":")); } return super.parsePersistentId(pidString); } @Override public GlobalId parsePersistentId(String protocol, String identifierString) { - if (!HandlenetServiceBean.HDL_PROTOCOL.equals(protocol)) { + if (!HandlePidProvider.HDL_PROTOCOL.equals(protocol)) { return null; } GlobalId globalId = super.parsePersistentId(protocol, identifierString); @@ -92,7 +91,7 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { @Override public GlobalId parsePersistentId(String protocol, String authority, String identifier) { - if (!HandlenetServiceBean.HDL_PROTOCOL.equals(protocol)) { + if (!HandlePidProvider.HDL_PROTOCOL.equals(protocol)) { return null; } return super.parsePersistentId(protocol, authority, identifier); @@ -100,6 +99,6 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden @Override public String getUrlPrefix() { - return HandlenetServiceBean.HDL_RESOLVER_URL; + return HandlePidProvider.HDL_RESOLVER_URL; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteRegisterCache.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterCache.java similarity index 97% rename from src/main/java/edu/harvard/iq/dataverse/DOIDataCiteRegisterCache.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterCache.java index 7c75b1a4da6..32cef08b4f7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteRegisterCache.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterCache.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders.datacite; import java.io.Serializable; diff --git a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java similarity index 95% rename from src/main/java/edu/harvard/iq/dataverse/DOIDataCiteRegisterService.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java index 9ecc4a3ecc9..2df5fc818ab 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java @@ -3,9 +3,18 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse; - +package edu.harvard.iq.dataverse.pidproviders.datacite; + +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetAuthor; +import edu.harvard.iq.dataverse.DatasetField; +import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.branding.BrandingUtil; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider.GlobalIdMetadataTemplate; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -47,7 +56,7 @@ public class DOIDataCiteRegisterService { DataverseServiceBean dataverseService; @EJB - DOIDataCiteServiceBean doiDataCiteServiceBean; + DataCiteDOIProvider doiDataCiteServiceBean; //A singleton since it, and the httpClient in it can be reused. @@ -183,7 +192,7 @@ public static String getMetadataFromDvObject(String identifier, Map from HTML, it leaves '&' (at least so we need to xml escape as well String description = StringEscapeUtils.escapeXml10(dataset.getLatestVersion().getDescriptionPlainText()); if (description.isEmpty() || description.equals(DatasetField.NA_VALUE)) { - description = AbstractGlobalIdServiceBean.UNAVAILABLE; + description = AbstractPidProvider.UNAVAILABLE; } metadataTemplate.setDescription(description); } @@ -192,7 +201,7 @@ public static String getMetadataFromDvObject(String identifier, Map getMetadata(String identifier) throws IOException try { DataCiteRESTfullClient client = getClient(); String xmlMetadata = client.getMetadata(identifier.substring(identifier.indexOf(":") + 1)); - DOIDataCiteServiceBean.GlobalIdMetadataTemplate template = doiDataCiteServiceBean.new GlobalIdMetadataTemplate(xmlMetadata); + AbstractPidProvider.GlobalIdMetadataTemplate template = doiDataCiteServiceBean.new GlobalIdMetadataTemplate(xmlMetadata); metadata.put("datacite.creator", Util.getStrFromList(template.getCreators())); metadata.put("datacite.title", template.getTitle()); metadata.put("datacite.publisher", template.getPublisher()); @@ -507,7 +516,7 @@ public String generateXML(DvObject dvObject) { } } else { - creatorsElement.append("").append(AbstractGlobalIdServiceBean.UNAVAILABLE).append(""); + creatorsElement.append("").append(AbstractPidProvider.UNAVAILABLE).append(""); } xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); @@ -650,7 +659,7 @@ public void setPublisherYear(String publisherYear) { } } -class Util { +public class Util { public static void close(InputStream in) { if (in != null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/DataCiteRESTfullClient.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DataCiteRESTfullClient.java similarity index 99% rename from src/main/java/edu/harvard/iq/dataverse/DataCiteRESTfullClient.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DataCiteRESTfullClient.java index 491f19ab36c..2c4e94c1f79 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataCiteRESTfullClient.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DataCiteRESTfullClient.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders.datacite; import java.io.Closeable; diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JSONLDUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JSONLDUtil.java index 4fb3ffe6c14..637f002f5ad 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/json/JSONLDUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JSONLDUtil.java @@ -39,7 +39,6 @@ import edu.harvard.iq.dataverse.DatasetFieldValue; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.MetadataBlock; import edu.harvard.iq.dataverse.MetadataBlockServiceBean; import edu.harvard.iq.dataverse.TermsOfUseAndAccess; @@ -52,6 +51,7 @@ import edu.harvard.iq.dataverse.DatasetVersion.VersionState; import edu.harvard.iq.dataverse.license.License; import edu.harvard.iq.dataverse.license.LicenseServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import jakarta.json.JsonReader; public class JSONLDUtil { @@ -83,7 +83,7 @@ public static Dataset updateDatasetMDFromJsonLD(Dataset ds, String jsonLDBody, JsonObject jsonld = decontextualizeJsonLD(jsonLDBody); if (migrating) { - Optional maybePid = GlobalIdServiceBean.parse(jsonld.getString("@id")); + Optional maybePid = PidProvider.parse(jsonld.getString("@id")); if (maybePid.isPresent()) { ds.setGlobalId(maybePid.get()); } else { diff --git a/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java b/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java index 394f08c6e93..96c6228f386 100644 --- a/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java @@ -3,6 +3,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -19,7 +21,7 @@ public class GlobalIdTest { @Test public void testValidDOI() { System.out.println("testValidDOI"); - GlobalId instance = new GlobalId(DOIServiceBean.DOI_PROTOCOL,"10.5072","FK2/BYM3IW", "/", DOIServiceBean.DOI_RESOLVER_URL, null); + GlobalId instance = new GlobalId(DOIProvider.DOI_PROTOCOL,"10.5072","FK2/BYM3IW", "/", DOIProvider.DOI_RESOLVER_URL, null); assertEquals("doi", instance.getProtocol()); assertEquals("10.5072", instance.getAuthority()); @@ -30,7 +32,7 @@ public void testValidDOI() { @Test public void testValidHandle() { System.out.println("testValidDOI"); - GlobalId instance = new GlobalId(HandlenetServiceBean.HDL_PROTOCOL, "1902.1","111012", "/", HandlenetServiceBean.HDL_RESOLVER_URL, null); + GlobalId instance = new GlobalId(HandlePidProvider.HDL_PROTOCOL, "1902.1","111012", "/", HandlePidProvider.HDL_RESOLVER_URL, null); assertEquals("hdl", instance.getProtocol()); assertEquals("1902.1", instance.getAuthority()); @@ -57,7 +59,7 @@ public void testInject() { System.out.println("testInject (weak test)"); // String badProtocol = "hdl:'Select value from datasetfieldvalue';/ha"; - GlobalId instance = PidUtil.parseAsGlobalID(HandlenetServiceBean.HDL_PROTOCOL, "'Select value from datasetfieldvalue';", "ha"); + GlobalId instance = PidUtil.parseAsGlobalID(HandlePidProvider.HDL_PROTOCOL, "'Select value from datasetfieldvalue';", "ha"); assertNull(instance); //exception.expect(IllegalArgumentException.class); diff --git a/src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java index 542d00d0d78..da25e65fc35 100644 --- a/src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java @@ -7,8 +7,12 @@ import edu.harvard.iq.dataverse.engine.TestCommandContext; import edu.harvard.iq.dataverse.engine.command.CommandContext; -import edu.harvard.iq.dataverse.pidproviders.FakePidProviderServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -33,13 +37,13 @@ public class PersistentIdentifierServiceBeanTest { private SettingsServiceBean settingsServiceBean; @InjectMocks - DOIEZIdServiceBean ezidServiceBean = new DOIEZIdServiceBean(); + DOIEZIdProvider ezidServiceBean = new DOIEZIdProvider(); @InjectMocks - DOIDataCiteServiceBean dataCiteServiceBean = new DOIDataCiteServiceBean(); + DataCiteDOIProvider dataCiteServiceBean = new DataCiteDOIProvider(); @InjectMocks - FakePidProviderServiceBean fakePidProviderServiceBean = new FakePidProviderServiceBean(); - HandlenetServiceBean hdlServiceBean = new HandlenetServiceBean(); - PermaLinkPidProviderServiceBean permaLinkServiceBean = new PermaLinkPidProviderServiceBean(); + FakeDOIProvider fakePidProviderServiceBean = new FakeDOIProvider(); + HandlePidProvider hdlServiceBean = new HandlePidProvider(); + PermaLinkPidProvider permaLinkServiceBean = new PermaLinkPidProvider(); CommandContext ctxt; @@ -48,27 +52,27 @@ public void setup() { MockitoAnnotations.initMocks(this); ctxt = new TestCommandContext(){ @Override - public HandlenetServiceBean handleNet() { + public HandlePidProvider handleNet() { return hdlServiceBean; } @Override - public DOIDataCiteServiceBean doiDataCite() { + public DataCiteDOIProvider doiDataCite() { return dataCiteServiceBean; } @Override - public DOIEZIdServiceBean doiEZId() { + public DOIEZIdProvider doiEZId() { return ezidServiceBean; } @Override - public FakePidProviderServiceBean fakePidProvider() { + public FakeDOIProvider fakePidProvider() { return fakePidProviderServiceBean; } @Override - public PermaLinkPidProviderServiceBean permaLinkProvider() { + public PermaLinkPidProvider permaLinkProvider() { return permaLinkServiceBean; } @@ -84,34 +88,34 @@ public void testGetBean_String_CommandContext_OK() { Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("EZID"); assertEquals(ezidServiceBean, - GlobalIdServiceBean.getBean("doi", ctxt)); + PidProvider.getBean("doi", ctxt)); ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "DataCite"); Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("DataCite"); assertEquals(dataCiteServiceBean, - GlobalIdServiceBean.getBean("doi", ctxt)); + PidProvider.getBean("doi", ctxt)); ctxt.settings().setValueForKey(SettingsServiceBean.Key.DoiProvider, "FAKE"); Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("FAKE"); assertEquals(fakePidProviderServiceBean, - GlobalIdServiceBean.getBean("doi", ctxt)); + PidProvider.getBean("doi", ctxt)); assertEquals(hdlServiceBean, - GlobalIdServiceBean.getBean("hdl", ctxt)); + PidProvider.getBean("hdl", ctxt)); assertEquals(permaLinkServiceBean, - GlobalIdServiceBean.getBean("perma", ctxt)); + PidProvider.getBean("perma", ctxt)); } @Test public void testGetBean_String_CommandContext_BAD() { ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "non-existent-provider"); - assertNull(GlobalIdServiceBean.getBean("doi", ctxt)); + assertNull(PidProvider.getBean("doi", ctxt)); - assertNull(GlobalIdServiceBean.getBean("non-existent-protocol", ctxt)); + assertNull(PidProvider.getBean("non-existent-protocol", ctxt)); } /** @@ -124,15 +128,15 @@ public void testGetBean_CommandContext() { Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("EZID"); assertEquals(ezidServiceBean, - GlobalIdServiceBean.getBean("doi", ctxt)); + PidProvider.getBean("doi", ctxt)); ctxt.settings().setValueForKey( SettingsServiceBean.Key.Protocol, "hdl"); assertEquals(hdlServiceBean, - GlobalIdServiceBean.getBean("hdl", ctxt)); + PidProvider.getBean("hdl", ctxt)); ctxt.settings().setValueForKey( SettingsServiceBean.Key.Protocol, "perma"); assertEquals(permaLinkServiceBean, - GlobalIdServiceBean.getBean("perma", ctxt)); + PidProvider.getBean("perma", ctxt)); } diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java index ad980aa28cd..8993566b7ab 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java @@ -3,11 +3,11 @@ */ package edu.harvard.iq.dataverse.dataaccess; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.mocks.MocksFactory; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -94,8 +94,8 @@ public static void tearDown() { void testGlobusOverlayIdentifiers() throws IOException { dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, authority, identifier, "/", - DOIServiceBean.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, authority, identifier, "/", + DOIProvider.DOI_RESOLVER_URL, null)); mDatafile = MocksFactory.makeDataFile(); mDatafile.setOwner(dataset); mDatafile.setStorageIdentifier("globusm://" + baseStoreId1); diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java index 1c371881ba6..90c7595a5e0 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java @@ -4,11 +4,11 @@ */ package edu.harvard.iq.dataverse.dataaccess; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.mocks.MocksFactory; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.util.UrlSignerUtil; import org.junit.jupiter.api.AfterEach; @@ -50,7 +50,7 @@ public void setUp() { System.setProperty("dataverse.files.file.label", "default"); datafile = MocksFactory.makeDataFile(); dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, authority, identifier, "/", DOIServiceBean.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, authority, identifier, "/", DOIProvider.DOI_RESOLVER_URL, null)); datafile.setOwner(dataset); datafile.setStorageIdentifier("test://" + baseStoreId + "//" + logoPath); diff --git a/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java b/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java index a80adb33b8d..2b509254f0e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java +++ b/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java @@ -11,8 +11,11 @@ import edu.harvard.iq.dataverse.engine.command.Command; import edu.harvard.iq.dataverse.engine.command.CommandContext; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.FakePidProviderServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProviderServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -122,27 +125,27 @@ public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels() { } @Override - public DOIEZIdServiceBean doiEZId() { + public DOIEZIdProvider doiEZId() { return null; } @Override - public DOIDataCiteServiceBean doiDataCite() { + public DataCiteDOIProvider doiDataCite() { return null; } @Override - public FakePidProviderServiceBean fakePidProvider() { + public FakeDOIProvider fakePidProvider() { return null; } @Override - public HandlenetServiceBean handleNet() { + public HandlePidProvider handleNet() { return null; } @Override - public PermaLinkPidProviderServiceBean permaLinkProvider() { + public PermaLinkPidProvider permaLinkProvider() { return null; } diff --git a/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java index 76ca853d5cc..8ca5b235256 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java @@ -7,12 +7,13 @@ import com.google.gson.Gson; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.HandlenetServiceBean; import edu.harvard.iq.dataverse.api.dto.DatasetDTO; import edu.harvard.iq.dataverse.api.dto.DatasetVersionDTO; import edu.harvard.iq.dataverse.export.openaire.OpenAireExportUtil; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; + import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; @@ -56,7 +57,7 @@ public void testWriteIdentifierElementDoi() throws XMLStreamException { String persistentAgency = "doi"; String persistentAuthority = "10.123"; String persistentId = "123"; - GlobalId globalId = new GlobalId(persistentAgency, persistentAuthority, persistentId, null, DOIServiceBean.DOI_RESOLVER_URL, null); + GlobalId globalId = new GlobalId(persistentAgency, persistentAuthority, persistentId, null, DOIProvider.DOI_RESOLVER_URL, null); // when OpenAireExportUtil.writeIdentifierElement(xmlWriter, globalId.asURL(), null); @@ -76,7 +77,7 @@ public void testWriteIdentifierElementHandle() throws XMLStreamException { String persistentAgency = "hdl"; String persistentAuthority = "1902.1"; String persistentId = "111012"; - GlobalId globalId = new GlobalId(persistentAgency, persistentAuthority, persistentId, null, HandlenetServiceBean.HDL_RESOLVER_URL, null); + GlobalId globalId = new GlobalId(persistentAgency, persistentAuthority, persistentId, null, HandlePidProvider.HDL_RESOLVER_URL, null); // when OpenAireExportUtil.writeIdentifierElement(xmlWriter, globalId.asURL(), null); diff --git a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java index 6f0132e2bc9..e90573a52a9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java @@ -1,6 +1,5 @@ package edu.harvard.iq.dataverse.externaltools; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.DataFileServiceBean; import edu.harvard.iq.dataverse.Dataset; @@ -9,6 +8,7 @@ import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.users.ApiToken; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.URLTokenUtil; import edu.harvard.iq.dataverse.util.json.JsonUtil; @@ -267,7 +267,7 @@ public void testDatasetConfigureTool() { .build().toString()); var dataset = new Dataset(); - dataset.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, "10.5072", "ABC123", null, DOIServiceBean.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.5072", "ABC123", null, DOIProvider.DOI_RESOLVER_URL, null)); ApiToken nullApiToken = null; String nullLocaleCode = "en"; var externalToolHandler = new ExternalToolHandler(externalTool, dataset, nullApiToken, nullLocaleCode); diff --git a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java index 4f5af8b97b0..606afba9b04 100644 --- a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java @@ -1,6 +1,5 @@ package edu.harvard.iq.dataverse.externaltools; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.DataFileServiceBean; import edu.harvard.iq.dataverse.DataTable; @@ -9,6 +8,7 @@ import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.users.ApiToken; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.util.URLTokenUtil; import java.util.ArrayList; @@ -144,7 +144,7 @@ public void testParseAddFileToolFilePid() { assertEquals("explorer", externalTool.getToolName()); DataFile dataFile = new DataFile(); dataFile.setId(42l); - dataFile.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL,"10.5072","FK2/RMQT6J/G9F1A1", "/", DOIServiceBean.DOI_RESOLVER_URL, null)); + dataFile.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL,"10.5072","FK2/RMQT6J/G9F1A1", "/", DOIProvider.DOI_RESOLVER_URL, null)); FileMetadata fmd = new FileMetadata(); fmd.setId(2L); DatasetVersion dv = new DatasetVersion(); diff --git a/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java index 56f8731b9c8..95e391071bc 100644 --- a/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java @@ -13,7 +13,6 @@ import org.mockito.Mock; import org.mockito.Mockito; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.GlobalId; @@ -21,6 +20,7 @@ import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.GlobusAccessibleStore; import edu.harvard.iq.dataverse.mocks.MocksFactory; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.util.json.JsonUtil; import jakarta.json.JsonObject; @@ -52,8 +52,8 @@ public void setUp() { "d7c42580-6538-4605-9ad8-116a61982644/hdc1"); dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, authority, identifier, "/", - DOIServiceBean.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, authority, identifier, "/", + DOIProvider.DOI_RESOLVER_URL, null)); mDatafile = MocksFactory.makeDataFile(); mDatafile.setOwner(dataset); mDatafile.setStorageIdentifier("globusm://" + baseStoreId1); diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index dabc7f68fce..ccf0de93f25 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -1,8 +1,6 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.GlobalIdServiceBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.json.JsonUtil; import java.io.IOException; @@ -32,7 +30,7 @@ public class PidUtilTest { @Mock private SettingsServiceBean settingsServiceBean; @InjectMocks - private PermaLinkPidProviderServiceBean p = new PermaLinkPidProviderServiceBean(); + private PermaLinkPidProvider p = new PermaLinkPidProvider(); @BeforeEach @@ -49,7 +47,7 @@ public void testGetDoi() throws IOException { String username = System.getenv("DataCiteUsername"); String password = System.getenv("DataCitePassword"); String baseUrl = "https://api.test.datacite.org"; - GlobalId pid = new GlobalId(DOIServiceBean.DOI_PROTOCOL,"10.70122","QE5A-XN55", "/", DOIServiceBean.DOI_RESOLVER_URL, null); + GlobalId pid = new GlobalId(DOIProvider.DOI_PROTOCOL,"10.70122","QE5A-XN55", "/", DOIProvider.DOI_RESOLVER_URL, null); try { JsonObjectBuilder result = PidUtil.queryDoi(pid, baseUrl, username, password); String out = JsonUtil.prettyPrint(result.build()); @@ -61,12 +59,12 @@ public void testGetDoi() throws IOException { @Test public void testGetPermaLink() throws IOException { - List list = new ArrayList(); + List list = new ArrayList(); list.add(p); PidUtil.addAllToProviderList(list); - GlobalId pid = new GlobalId(PermaLinkPidProviderServiceBean.PERMA_PROTOCOL,"DANSLINK","QE5A-XN55", "", p.getUrlPrefix(), PermaLinkPidProviderServiceBean.PERMA_PROVIDER_NAME); + GlobalId pid = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE5A-XN55", "", p.getUrlPrefix(), PermaLinkPidProvider.PERMA_PROVIDER_NAME); System.out.println(pid.asString()); System.out.println(pid.asURL()); diff --git a/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java index adf48e05f09..c0e592e3194 100644 --- a/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java @@ -4,6 +4,7 @@ import edu.harvard.iq.dataverse.Dataverse.DataverseType; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.mocks.MocksFactory; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; @@ -134,7 +135,7 @@ private DatasetField constructBoundingBoxValue(String datasetFieldTypeName, Stri private IndexableDataset createIndexableDataset() { final Dataset dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL,"10.666", "FAKE/fake", "/", DOIServiceBean.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL,"10.666", "FAKE/fake", "/", DOIProvider.DOI_RESOLVER_URL, null)); final DatasetVersion datasetVersion = dataset.getCreateVersion(null); DatasetField field = createCVVField("language", "English", false); datasetVersion.getDatasetFields().add(field); diff --git a/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java index 41032ffa811..c61c1ebc75d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java @@ -1,11 +1,11 @@ package edu.harvard.iq.dataverse.sitemap; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.harvest.client.HarvestingClient; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.util.xml.XmlPrinter; import edu.harvard.iq.dataverse.util.xml.XmlValidator; import java.io.File; @@ -66,14 +66,14 @@ void testUpdateSiteMap() throws IOException, ParseException, SAXException { List datasets = new ArrayList<>(); Dataset published = new Dataset(); - published.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, "10.666", "FAKE/published1", null, DOIServiceBean.DOI_RESOLVER_URL, null)); + published.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/published1", null, DOIProvider.DOI_RESOLVER_URL, null)); String publishedPid = published.getGlobalId().asString(); published.setPublicationDate(new Timestamp(new Date().getTime())); published.setModificationTime(new Timestamp(new Date().getTime())); datasets.add(published); Dataset unpublished = new Dataset(); - unpublished.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, "10.666", "FAKE/unpublished1", null, DOIServiceBean.DOI_RESOLVER_URL, null)); + unpublished.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/unpublished1", null, DOIProvider.DOI_RESOLVER_URL, null)); String unpublishedPid = unpublished.getGlobalId().asString(); Timestamp nullPublicationDateToIndicateNotPublished = null; @@ -81,14 +81,14 @@ void testUpdateSiteMap() throws IOException, ParseException, SAXException { datasets.add(unpublished); Dataset harvested = new Dataset(); - harvested.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, "10.666", "FAKE/harvested1", null, DOIServiceBean.DOI_RESOLVER_URL, null)); + harvested.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/harvested1", null, DOIProvider.DOI_RESOLVER_URL, null)); String harvestedPid = harvested.getGlobalId().asString(); harvested.setPublicationDate(new Timestamp(new Date().getTime())); harvested.setHarvestedFrom(new HarvestingClient()); datasets.add(harvested); Dataset deaccessioned = new Dataset(); - deaccessioned.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL, "10.666", "FAKE/deaccessioned1", null, DOIServiceBean.DOI_RESOLVER_URL, null)); + deaccessioned.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/deaccessioned1", null, DOIProvider.DOI_RESOLVER_URL, null)); String deaccessionedPid = deaccessioned.getGlobalId().asString(); deaccessioned.setPublicationDate(new Timestamp(new Date().getTime())); diff --git a/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java index d70a108e7c6..c8bb6c99ac2 100644 --- a/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java @@ -1,12 +1,12 @@ package edu.harvard.iq.dataverse.util; -import edu.harvard.iq.dataverse.DOIServiceBean; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.users.ApiToken; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.testing.JvmSetting; import edu.harvard.iq.dataverse.util.testing.LocalJvmSettings; @@ -32,7 +32,7 @@ void testGetToolUrlWithOptionalQueryParameters() { DatasetVersion dv = new DatasetVersion(); Dataset ds = new Dataset(); ds.setId(50L); - ds.setGlobalId(new GlobalId(DOIServiceBean.DOI_PROTOCOL,"10.5072","FK2ABCDEF",null, DOIServiceBean.DOI_RESOLVER_URL, null)); + ds.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL,"10.5072","FK2ABCDEF",null, DOIProvider.DOI_RESOLVER_URL, null)); dv.setDataset(ds); fmd.setDatasetVersion(dv); List fmdl = new ArrayList<>(); From 9a662215c1ca83aaf903711c51518de29c6c1063 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 3 Jan 2024 13:36:43 -0500 Subject: [PATCH 004/113] remove Util class --- .../datacite/DOIDataCiteRegisterService.java | 66 ++----------------- 1 file changed, 6 insertions(+), 60 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java index 2df5fc818ab..60cb089b961 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java @@ -40,6 +40,8 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import java.nio.charset.StandardCharsets; + /** * * @author luopc @@ -186,7 +188,7 @@ public static String getMetadataFromDvObject(String identifier, Map from HTML, it leaves '&' (at least so we need to xml escape as well @@ -237,7 +239,7 @@ public static String getMetadataForDeactivateIdentifier(String identifier, Map getMetadata(String identifier) throws IOException DataCiteRESTfullClient client = getClient(); String xmlMetadata = client.getMetadata(identifier.substring(identifier.indexOf(":") + 1)); AbstractPidProvider.GlobalIdMetadataTemplate template = doiDataCiteServiceBean.new GlobalIdMetadataTemplate(xmlMetadata); - metadata.put("datacite.creator", Util.getStrFromList(template.getCreators())); + metadata.put("datacite.creator", String.join("; ", template.getCreators())); metadata.put("datacite.title", template.getTitle()); metadata.put("datacite.publisher", template.getPublisher()); metadata.put("datacite.publicationyear", template.getPublisherYear()); @@ -384,7 +386,7 @@ class DataCiteMetadataTemplate { static { try (InputStream in = DataCiteMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { - template = Util.readAndClose(in, "utf-8"); + template = new String(in.readAllBytes(),StandardCharset.UTF_8); } catch (Exception e) { logger.log(Level.SEVERE, "datacite metadata template load error"); logger.log(Level.SEVERE, "String " + e.toString()); @@ -658,59 +660,3 @@ public void setPublisherYear(String publisherYear) { this.publisherYear = publisherYear; } } - -public class Util { - - public static void close(InputStream in) { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - throw new RuntimeException("Fail to close InputStream"); - } - } - } - - public static String readAndClose(InputStream inStream, String encoding) { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - byte[] buf = new byte[128]; - String data; - try { - int cnt; - while ((cnt = inStream.read(buf)) >= 0) { - outStream.write(buf, 0, cnt); - } - data = outStream.toString(encoding); - } catch (IOException ioe) { - throw new RuntimeException("IOException"); - } finally { - close(inStream); - } - return data; - } - - public static List getListFromStr(String str) { - return Arrays.asList(str.split("; ")); -// List authors = new ArrayList(); -// int preIdx = 0; -// for(int i=0;i authors) { - StringBuilder str = new StringBuilder(); - for (String author : authors) { - if (str.length() > 0) { - str.append("; "); - } - str.append(author); - } - return str.toString(); - } - -} From 023bb56d524a3ac4927588de63ef78a560c04f14 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 09:49:10 -0500 Subject: [PATCH 005/113] rename --- .../pidproviders/{DOIEZIdProvider.java => EZIdDOIProvider.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{DOIEZIdProvider.java => EZIdDOIProvider.java} (100%) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIEZIdProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java similarity index 100% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIEZIdProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java From 339ba167d1c4aa4c697acc318fb724c76b6474ba Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 09:50:03 -0500 Subject: [PATCH 006/113] add factories for all, fix providers, etc. --- .../iq/dataverse/DatasetServiceBean.java | 4 - .../iq/dataverse/EjbDataverseEngine.java | 6 +- .../engine/command/CommandContext.java | 4 +- .../pidproviders/AbstractPidProvider.java | 134 +++++++++------ .../dataverse/pidproviders/DOIProvider.java | 23 +-- .../pidproviders/DataCiteDOIProvider.java | 153 +++++++++--------- .../pidproviders/DataCiteProviderFactory.java | 20 ++- .../pidproviders/EZIdDOIProvider.java | 31 ++-- .../pidproviders/EZIdProviderFactory.java | 36 +++++ .../pidproviders/FakeDOIProvider.java | 15 +- .../pidproviders/FakeProviderFactory.java | 32 ++++ .../pidproviders/HandlePidProvider.java | 68 ++++---- .../pidproviders/HandleProviderFactory.java | 37 +++++ .../pidproviders/PermaLinkPidProvider.java | 101 ++++++------ .../PermaLinkProviderFactory.java | 34 ++++ .../dataverse/pidproviders/PidProvider.java | 8 +- .../pidproviders/PidProviderFactoryBean.java | 35 +++- .../pidproviders/UnmanagedDOIProvider.java | 12 +- .../datacite/DOIDataCiteRegisterService.java | 2 +- .../iq/dataverse/settings/JvmSettings.java | 6 +- .../iq/dataverse/util/SystemConfig.java | 11 +- 21 files changed, 488 insertions(+), 284 deletions(-) create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java index 4ee74d0d53a..0aedc082eca 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java @@ -19,7 +19,6 @@ import edu.harvard.iq.dataverse.export.ExportService; import edu.harvard.iq.dataverse.globus.GlobusServiceBean; import edu.harvard.iq.dataverse.harvest.server.OAIRecordServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; @@ -63,9 +62,6 @@ public class DatasetServiceBean implements java.io.Serializable { @EJB IndexServiceBean indexService; - @EJB - DOIEZIdProvider doiEZIdServiceBean; - @EJB SettingsServiceBean settingsService; diff --git a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java index 64c7380fab7..a5a16f1ba03 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java +++ b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java @@ -17,7 +17,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.EZIdDOIProvider; import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; @@ -117,7 +117,7 @@ public class EjbDataverseEngine { DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels; @EJB - DOIEZIdProvider doiEZId; + EZIdDOIProvider doiEZId; @EJB DataCiteDOIProvider doiDataCite; @@ -487,7 +487,7 @@ public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels() { } @Override - public DOIEZIdProvider doiEZId() { + public EZIdDOIProvider doiEZId() { return doiEZId; } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java index 397bbb333bc..8447bf7a146 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java @@ -29,7 +29,7 @@ import edu.harvard.iq.dataverse.datacapturemodule.DataCaptureModuleServiceBean; import edu.harvard.iq.dataverse.engine.DataverseEngine; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; +import edu.harvard.iq.dataverse.pidproviders.EZIdDOIProvider; import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; @@ -100,7 +100,7 @@ public interface CommandContext { public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels(); - public DOIEZIdProvider doiEZId(); + public EZIdDOIProvider doiEZId(); public DataCiteDOIProvider doiDataCite(); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index c0da9eafea8..bf4a8e9c7de 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -4,16 +4,11 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetAuthor; import edu.harvard.iq.dataverse.DatasetField; -import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DvObject; -import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.pidproviders.datacite.Util; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; import java.io.InputStream; -import jakarta.ejb.EJB; -import jakarta.inject.Inject; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -24,25 +19,41 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; + + public abstract class AbstractPidProvider implements PidProvider { private static final Logger logger = Logger.getLogger(AbstractPidProvider.class.getCanonicalName()); - @Inject - DataverseServiceBean dataverseService; - @EJB - protected - SettingsServiceBean settingsService; - @Inject - protected - DvObjectServiceBean dvObjectService; - @Inject - SystemConfig systemConfig; - - protected Boolean configured = null; - public static String UNAVAILABLE = ":unav"; + PidProviderFactoryBean pidProviderService; + + private String protocol; + + private String authority; + + private String shoulder; + + private String identifierGenerationStyle; + + private String datafilePidFormat; + + private List managedList; + + private List excludedList; + + AbstractPidProvider(String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + this.protocol = protocol; + this.authority = authority; + this.shoulder = shoulder; + this.identifierGenerationStyle = identifierGenerationStyle; + this.datafilePidFormat = datafilePidFormat; + this.managedList = Arrays.asList(managedList.split(",\\s")); + this.excludedList = Arrays.asList(excludedList.split(",\\s")); + + } + @Override public Map getMetadataForCreateIndicator(DvObject dvObjectIn) { logger.log(Level.FINE,"getMetadataForCreateIndicator(DvObject)"); @@ -67,7 +78,7 @@ protected Map addBasicMetadata(DvObject dvObjectIn, Map addDOIMetadataForDestroyedDataset(DvObject dvObjec protected String getTargetUrl(DvObject dvObjectIn) { logger.log(Level.FINE,"getTargetUrl"); - return systemConfig.getDataverseSiteUrl() + dvObjectIn.getTargetUrl() + dvObjectIn.getGlobalId().asString(); + return SystemConfig.getDataverseSiteUrlStatic() + dvObjectIn.getTargetUrl() + dvObjectIn.getGlobalId().asString(); } @Override @@ -150,8 +161,8 @@ public boolean alreadyRegistered(DvObject dvo) throws Exception { @Override public DvObject generateIdentifier(DvObject dvObject) { - String protocol = dvObject.getProtocol() == null ? settingsService.getValueForKey(SettingsServiceBean.Key.Protocol) : dvObject.getProtocol(); - String authority = dvObject.getAuthority() == null ? settingsService.getValueForKey(SettingsServiceBean.Key.Authority) : dvObject.getAuthority(); + String protocol = dvObject.getProtocol() == null ? getProtocol() : dvObject.getProtocol(); + String authority = dvObject.getAuthority() == null ? getAuthority() : dvObject.getAuthority(); if (dvObject.isInstanceofDataset()) { dvObject.setIdentifier(generateDatasetIdentifier((Dataset) dvObject)); } else { @@ -169,10 +180,9 @@ public DvObject generateIdentifier(DvObject dvObject) { //ToDo just send the DvObject.DType public String generateDatasetIdentifier(Dataset dataset) { //ToDo - track these in the bean - String identifierType = settingsService.getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "randomString"); - String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder, ""); + String shoulder = getShoulder(); - switch (identifierType) { + switch (getIdentifierGenerationStyle()) { case "randomString": return generateIdentifierAsRandomString(dataset, shoulder); case "storedProcGenerated": @@ -193,7 +203,7 @@ public String generateDatasetIdentifier(Dataset dataset) { * @return {@code true} if the identifier is unique, {@code false} otherwise. */ public boolean isGlobalIdUnique(GlobalId globalId) { - if ( ! dvObjectService.isGlobalIdLocallyUnique(globalId) ) { + if ( ! pidProviderService.isGlobalIdLocallyUnique(globalId)) { return false; // duplication found in local database } @@ -228,9 +238,6 @@ public boolean isGlobalIdUnique(GlobalId globalId) { */ @Override public GlobalId parsePersistentId(String fullIdentifierString) { - if(!isConfigured()) { - return null; - } // Occasionally, the protocol separator character ':' comes in still // URL-encoded as %3A (usually as a result of the URL having been // encoded twice): @@ -247,9 +254,6 @@ public GlobalId parsePersistentId(String fullIdentifierString) { } protected GlobalId parsePersistentId(String protocol, String identifierString) { - if(!isConfigured()) { - return null; - } String authority; String identifier; if (identifierString == null) { @@ -269,6 +273,8 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { if (PidProvider.testforNullTerminator(identifier)) { return null; } + ToDo - test specific authority/shoulder and against managed and excluded lists (should be maps?) + add unmanagedPermaProvider? } else { logger.log(Level.INFO, "Error parsing identifier: {0}: '':/'' not found in string", identifierString); @@ -278,9 +284,6 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { } public GlobalId parsePersistentId(String protocol, String authority, String identifier) { - if(!isConfigured()) { - return null; - } logger.fine("Parsing: " + protocol + ":" + authority + getSeparator() + identifier + " in " + getProviderInformation().get(0)); if(!PidProvider.isValidGlobalId(protocol, authority, identifier)) { return null; @@ -297,8 +300,7 @@ public String getSeparator() { @Override public String generateDataFileIdentifier(DataFile datafile) { - String doiIdentifierType = settingsService.getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "randomString"); - String doiDataFileFormat = settingsService.getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String doiDataFileFormat = getDatafilePidFormat(); String prepend = ""; if (doiDataFileFormat.equals(SystemConfig.DataFilePIDFormat.DEPENDENT.toString())){ @@ -308,12 +310,12 @@ public String generateDataFileIdentifier(DataFile datafile) { datafile.setAuthority(datafile.getOwner().getAuthority()); } else { //If there's a shoulder prepend independent identifiers with it - prepend = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder, ""); - datafile.setProtocol(settingsService.getValueForKey(SettingsServiceBean.Key.Protocol)); - datafile.setAuthority(settingsService.getValueForKey(SettingsServiceBean.Key.Authority)); + prepend = getShoulder(); + datafile.setProtocol(getProtocol()); + datafile.setAuthority(getAuthority()); } - switch (doiIdentifierType) { + switch (getIdentifierGenerationStyle()) { case "randomString": return generateIdentifierAsRandomString(datafile, prepend); case "storedProcGenerated": @@ -352,7 +354,7 @@ private String generateIdentifierAsRandomString(DvObject dvo, String prepend) { private String generateIdentifierFromStoredProcedureIndependent(DvObject dvo, String prepend) { String identifier; do { - String identifierFromStoredProcedure = dvObjectService.generateNewIdentifierByStoredProcedure(); + String identifierFromStoredProcedure = pidProviderService.generateNewIdentifierByStoredProcedure(); // some diagnostics here maybe - is it possible to determine that it's failing // because the stored procedure hasn't been created in the database? if (identifierFromStoredProcedure == null) { @@ -399,7 +401,7 @@ public class GlobalIdMetadataTemplate { public GlobalIdMetadataTemplate(){ try (InputStream in = GlobalIdMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { - template = Util.readAndClose(in, "utf-8"); + template = new String(in.readAllBytes(),StandardCharsets.UTF_8); } catch (Exception e) { logger.log(Level.SEVERE, "datacite metadata template load error"); logger.log(Level.SEVERE, "String " + e.toString()); @@ -666,7 +668,7 @@ public String getMetadataFromDvObject(String identifier, Map met GlobalIdMetadataTemplate metadataTemplate = new GlobalIdMetadataTemplate(); metadataTemplate.setIdentifier(identifier.substring(identifier.indexOf(':') + 1)); - metadataTemplate.setCreators(Util.getListFromStr(metadata.get("datacite.creator"))); + metadataTemplate.setCreators(Arrays.asList(metadata.get("datacite.creator").split("; "))); metadataTemplate.setAuthors(dataset.getLatestVersion().getDatasetAuthors()); if (dvObject.isInstanceofDataset()) { metadataTemplate.setDescription(dataset.getLatestVersion().getDescriptionPlainText()); @@ -680,7 +682,7 @@ public String getMetadataFromDvObject(String identifier, Map met metadataTemplate.setContacts(dataset.getLatestVersion().getDatasetContacts()); metadataTemplate.setProducers(dataset.getLatestVersion().getDatasetProducers()); metadataTemplate.setTitle(dvObject.getCurrentName()); - String producerString = dataverseService.getRootDataverseName(); + String producerString = pidProviderService.getProducer(); if (producerString.isEmpty() || producerString.equals(DatasetField.NA_VALUE) ) { producerString = UNAVAILABLE; } @@ -699,12 +701,40 @@ public boolean canManagePID() { } @Override - public boolean isConfigured() { - if(configured==null) { - return false; - } else { - return configured.booleanValue(); - } + public void setPidProviderServiceBean(PidProviderFactoryBean pidProviderServiceBean) { + this.pidProviderService = pidProviderServiceBean; + } + + @Override + public String getProtocol() { + return protocol; + } + + @Override + public String getAuthority() { + return authority; + } + + @Override + public String getShoulder() { + return shoulder; + } + + @Override + public String getIdentifierGenerationStyle() { + return identifierGenerationStyle; + } + + public String getDatafilePidFormat() { + return datafilePidFormat; + } + + public List getManagedList() { + return managedList; + } + + public List getExcludedList() { + return excludedList; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java index 1b1ed094613..cfdff3c3f51 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java @@ -1,7 +1,7 @@ package edu.harvard.iq.dataverse.pidproviders; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; + public abstract class DOIProvider extends AbstractPidProvider { @@ -11,8 +11,8 @@ public abstract class DOIProvider extends AbstractPidProvider { public static final String DXDOI_RESOLVER_URL = "https://dx.doi.org/"; public static final String HTTP_DXDOI_RESOLVER_URL = "http://dx.doi.org/"; - public DOIProvider() { - super(); + public DOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + super(DOI_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } @Override @@ -56,23 +56,6 @@ public String getUrlPrefix() { return DOI_RESOLVER_URL; } - @Override - public boolean isConfigured() { - if (configured == null) { - if (getProviderKeyName() == null) { - configured = false; - } else { - String doiProvider = settingsService.getValueForKey(Key.DoiProvider, ""); - if (getProviderKeyName().equals(doiProvider)) { - configured = true; - } else if (!doiProvider.isEmpty()) { - configured = false; - } - } - } - return super.isConfigured(); - } - protected String getProviderKeyName() { return null; } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index 1314af74c50..a15e60238ff 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -20,7 +20,6 @@ import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; - /** * * @author luopc @@ -28,7 +27,7 @@ public class DataCiteDOIProvider extends DOIProvider { private static final Logger logger = Logger.getLogger(DataCiteDOIProvider.class.getCanonicalName()); - + private static final String PUBLIC = "public"; private static final String FINDABLE = "findable"; private static final String RESERVED = "reserved"; @@ -39,35 +38,41 @@ public class DataCiteDOIProvider extends DOIProvider { @EJB DOIDataCiteRegisterService doiDataCiteRegisterService; + public DataCiteDOIProvider(String providerAuthority, String providerShoulder, String managedList, + String excludedList, String mdsUrl, String apiUrl, String username, String password, + String identifierGenerationStyle, String datafilePidFormat) { + super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, + excludedList); + // TODO Auto-generated constructor stub + } + @Override public boolean registerWhenPublished() { return false; } - - @Override public boolean alreadyRegistered(GlobalId pid, boolean noProviderDefault) { - logger.log(Level.FINE,"alreadyRegistered"); - if(pid==null || pid.asString().isEmpty()) { + logger.log(Level.FINE, "alreadyRegistered"); + if (pid == null || pid.asString().isEmpty()) { logger.fine("No identifier sent."); return false; } boolean alreadyRegistered; String identifier = pid.asString(); - try{ - alreadyRegistered = doiDataCiteRegisterService.testDOIExists(identifier); - } catch (Exception e){ + try { + alreadyRegistered = doiDataCiteRegisterService.testDOIExists(identifier); + } catch (Exception e) { logger.log(Level.WARNING, "alreadyRegistered failed"); return false; } - return alreadyRegistered; + return alreadyRegistered; } @Override public String createIdentifier(DvObject dvObject) throws Exception { - logger.log(Level.FINE,"createIdentifier"); - if(dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty() ){ + logger.log(Level.FINE, "createIdentifier"); + if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { dvObject = generateIdentifier(dvObject); } String identifier = getIdentifier(dvObject); @@ -85,7 +90,7 @@ public String createIdentifier(DvObject dvObject) throws Exception { @Override public Map getIdentifierMetadata(DvObject dvObject) { - logger.log(Level.FINE,"getIdentifierMetadata"); + logger.log(Level.FINE, "getIdentifierMetadata"); String identifier = getIdentifier(dvObject); Map metadata = new HashMap<>(); try { @@ -95,20 +100,20 @@ public Map getIdentifierMetadata(DvObject dvObject) { } return metadata; } - /** * Modifies the DOI metadata for a Dataset + * * @param dvObject the dvObject whose metadata needs to be modified * @return the Dataset identifier, or null if the modification failed * @throws java.lang.Exception */ @Override public String modifyIdentifierTargetURL(DvObject dvObject) throws Exception { - logger.log(Level.FINE,"modifyIdentifier"); + logger.log(Level.FINE, "modifyIdentifier"); String identifier = getIdentifier(dvObject); try { - HashMap metadata = doiDataCiteRegisterService.getMetadata(identifier); + HashMap metadata = doiDataCiteRegisterService.getMetadata(identifier); doiDataCiteRegisterService.modifyIdentifier(identifier, metadata, dvObject); } catch (Exception e) { logger.log(Level.WARNING, "modifyMetadata failed", e); @@ -116,9 +121,9 @@ public String modifyIdentifierTargetURL(DvObject dvObject) throws Exception { } return identifier; } - - public void deleteRecordFromCache(Dataset datasetIn){ - logger.log(Level.FINE,"deleteRecordFromCache"); + + public void deleteRecordFromCache(Dataset datasetIn) { + logger.log(Level.FINE, "deleteRecordFromCache"); String identifier = getIdentifier(datasetIn); HashMap doiMetadata = new HashMap(); try { @@ -140,7 +145,7 @@ public void deleteRecordFromCache(Dataset datasetIn){ } catch (Exception e) { logger.log(Level.WARNING, "delete failed"); logger.log(Level.WARNING, "String {0}", e.toString()); - logger.log(Level.WARNING, "localized message {0}", e.getLocalizedMessage()); + logger.log(Level.WARNING, "localized message {0}", e.getLocalizedMessage()); logger.log(Level.WARNING, "cause", e.getCause()); logger.log(Level.WARNING, "message {0}", e.getMessage()); throw new RuntimeException(e); @@ -149,78 +154,83 @@ public void deleteRecordFromCache(Dataset datasetIn){ } /* - * Deletes a DOI if it is in DRAFT/RESERVED state or removes metadata and changes it from PUBLIC/FINDABLE to REGISTERED. + * Deletes a DOI if it is in DRAFT/RESERVED state or removes metadata and + * changes it from PUBLIC/FINDABLE to REGISTERED. */ @Override public void deleteIdentifier(DvObject dvObject) throws IOException, HttpException { - logger.log(Level.FINE,"deleteIdentifier"); + logger.log(Level.FINE, "deleteIdentifier"); String identifier = getIdentifier(dvObject); - //ToDo - PidUtils currently has a DataCite API call that would get the status at DataCite for this identifier - that could be more accurate than assuming based on whether the dvObject has been published + // ToDo - PidUtils currently has a DataCite API call that would get the status + // at DataCite for this identifier - that could be more accurate than assuming + // based on whether the dvObject has been published String idStatus = DRAFT; - if(dvObject.isReleased()) { - idStatus = PUBLIC; - } - if ( idStatus != null ) { - switch ( idStatus ) { - case RESERVED: - case DRAFT: - logger.log(Level.INFO, "Delete status is reserved.."); - //service only removes the identifier from the cache (since it was written before DOIs could be registered in draft state) - doiDataCiteRegisterService.deleteIdentifier(identifier); - //So we call the deleteDraftIdentifier method below until things are refactored - deleteDraftIdentifier(dvObject); - break; + if (dvObject.isReleased()) { + idStatus = PUBLIC; + } + if (idStatus != null) { + switch (idStatus) { + case RESERVED: + case DRAFT: + logger.log(Level.INFO, "Delete status is reserved.."); + // service only removes the identifier from the cache (since it was written + // before DOIs could be registered in draft state) + doiDataCiteRegisterService.deleteIdentifier(identifier); + // So we call the deleteDraftIdentifier method below until things are refactored + deleteDraftIdentifier(dvObject); + break; - case PUBLIC: - case FINDABLE: - //if public then it has been released set to unavailable and reset target to n2t url - Map metadata = addDOIMetadataForDestroyedDataset(dvObject); - metadata.put("_status", "registered"); - metadata.put("_target", getTargetUrl(dvObject)); - doiDataCiteRegisterService.deactivateIdentifier(identifier, metadata, dvObject); - break; + case PUBLIC: + case FINDABLE: + // if public then it has been released set to unavailable and reset target to + // n2t url + Map metadata = addDOIMetadataForDestroyedDataset(dvObject); + metadata.put("_status", "registered"); + metadata.put("_target", getTargetUrl(dvObject)); + doiDataCiteRegisterService.deactivateIdentifier(identifier, metadata, dvObject); + break; } } } - + /** * Deletes DOI from the DataCite side, if possible. Only "draft" DOIs can be * deleted. */ private void deleteDraftIdentifier(DvObject dvObject) throws IOException { - - //ToDo - incorporate into DataCiteRESTfulClient + + // ToDo - incorporate into DataCiteRESTfulClient String baseUrl = JvmSettings.DATACITE_REST_API_URL.lookup("datacite"); String username = JvmSettings.DATACITE_USERNAME.lookup("datacite"); String password = JvmSettings.DATACITE_PASSWORD.lookup("datacite"); GlobalId doi = dvObject.getGlobalId(); /** - * Deletes the DOI from DataCite if it can. Returns 204 if PID was deleted - * (only possible for "draft" DOIs), 405 (method not allowed) if the DOI - * wasn't deleted (because it's in "findable" state, for example, 404 if the - * DOI wasn't found, and possibly other status codes such as 500 if DataCite - * is down. + * Deletes the DOI from DataCite if it can. Returns 204 if PID was deleted (only + * possible for "draft" DOIs), 405 (method not allowed) if the DOI wasn't + * deleted (because it's in "findable" state, for example, 404 if the DOI wasn't + * found, and possibly other status codes such as 500 if DataCite is down. */ - URL url = new URL(baseUrl + "/dois/" + doi.getAuthority() + "/" + doi.getIdentifier()); - HttpURLConnection connection = null; - connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("DELETE"); - String userpass = username + ":" + password; - String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes())); - connection.setRequestProperty("Authorization", basicAuth); - int status = connection.getResponseCode(); - if(status!=HttpStatus.SC_NO_CONTENT) { - logger.warning("Incorrect Response Status from DataCite: " + status + " : " + connection.getResponseMessage()); - throw new HttpException("Status: " + status); - } - logger.fine("deleteDoi status for " + doi.asString() + ": " + status); + URL url = new URL(baseUrl + "/dois/" + doi.getAuthority() + "/" + doi.getIdentifier()); + HttpURLConnection connection = null; + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("DELETE"); + String userpass = username + ":" + password; + String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes())); + connection.setRequestProperty("Authorization", basicAuth); + int status = connection.getResponseCode(); + if (status != HttpStatus.SC_NO_CONTENT) { + logger.warning( + "Incorrect Response Status from DataCite: " + status + " : " + connection.getResponseMessage()); + throw new HttpException("Status: " + status); + } + logger.fine("deleteDoi status for " + doi.asString() + ": " + status); } @Override public boolean publicizeIdentifier(DvObject dvObject) { - logger.log(Level.FINE,"updateIdentifierStatus"); - if(dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty() ){ + logger.log(Level.FINE, "updateIdentifierStatus"); + if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { dvObject = generateIdentifier(dvObject); } String identifier = getIdentifier(dvObject); @@ -237,29 +247,22 @@ public boolean publicizeIdentifier(DvObject dvObject) { } } - @Override - public List getProviderInformation(){ + public List getProviderInformation() { return List.of("DataCite", "https://status.datacite.org"); } - - @Override protected String getProviderKeyName() { return "DataCite"; } - - @Override public String getProviderType() { // TODO Auto-generated method stub return null; } - - @Override public String getName() { // TODO Auto-generated method stub diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index d1be90bda6d..d35354dc5fd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -1,27 +1,35 @@ package edu.harvard.iq.dataverse.pidproviders; import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.util.SystemConfig; -class DataCiteProviderFactory extends PidProviderFactory { - - public PidProvider createProvider(String providerName) { +class DataCiteProviderFactory implements PidProviderFactory { + + @Override + public PidProvider createPidProvider(String providerName) { String providerType=JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); if(!providerType.equals(DataCiteDOIProvider.TYPE)) { //Being asked to create a non-DataCite provider return null; } String providerAuthority=JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder=JvmSettings.PID_PROVIDER_SHOULDER.lookup(providerName); + String providerShoulder=JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + String identifierGenerationStyle=JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE.lookupOptional(providerName).orElse("randomString"); + String datafilePidFormat=JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName).orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + String mdsUrl=JvmSettings.DATACITE_MDS_API_URL.lookup(providerName); String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerName); String username = JvmSettings.DATACITE_USERNAME.lookup(providerName); String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); - String[] whitelist = JvmSettings.PID_PROVIDER_WHITELIST.lookup(providerName).split(","); + - return new DataCiteDOIProvider(providerAuthority, providerShoulder, mdsUrl, apiUrl, username, password); + return new DataCiteDOIProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); } public String getType() { return DataCiteDOIProvider.TYPE; } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java index 76c5c7f4450..4147815b5bf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java @@ -17,41 +17,40 @@ * * @author skraffmiller */ -public class DOIEZIdProvider extends DOIProvider { +public class EZIdDOIProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(DOIEZIdProvider.class.getCanonicalName()); + + + private static final Logger logger = Logger.getLogger(EZIdDOIProvider.class.getCanonicalName()); EZIDService ezidService; public static final String TYPE = "ezid"; - // This has a sane default in microprofile-config.properties - private final String baseUrl = JvmSettings.EZID_API_URL.lookup("ezid"); + private String baseUrl; - public DOIEZIdProvider() { + + public EZIdDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, + String datafilePidFormat, String managedList, String excludedList, String baseUrl, String username, String password) { + super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); // Creating the service doesn't do any harm, just initializing some object data here. // Makes sure we don't run into NPEs from the other methods, but will obviously fail if the // login below does not work. - this.ezidService = new EZIDService(this.baseUrl); + this.baseUrl = baseUrl; + this.ezidService = new EZIDService(baseUrl); try { - // These have (obviously) no default, but still are optional to make the provider optional - String username = JvmSettings.EZID_USERNAME.lookupOptional("ezid").orElse(null); - String password = JvmSettings.EZID_PASSWORD.lookupOptional("ezid").orElse(null); - - if (username != null ^ password != null) { - logger.log(Level.WARNING, "You must give both username and password. Will not try to login."); - } - + if (username != null && password != null) { this.ezidService.login(username, password); - this.configured = true; + } else { + logger.log(Level.WARNING, "You must give both username and password. Will not try to login."); } } catch (EZIDException e) { // We only do the warnings here, but the object still needs to be created. // The EJB stateless thing expects this to go through, and it is requested on any // global id parsing. - logger.log(Level.WARNING, "Login failed to {0}", this.baseUrl); + logger.log(Level.WARNING, "Login failed to {0}", baseUrl); logger.log(Level.WARNING, "Exception String: {0}", e.toString()); logger.log(Level.WARNING, "Localized message: {0}", e.getLocalizedMessage()); logger.log(Level.WARNING, "Cause:", e.getCause()); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java new file mode 100644 index 00000000000..26b3ada437e --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java @@ -0,0 +1,36 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.util.SystemConfig; + +class EZIdProviderFactory implements PidProviderFactory { + + @Override + public PidProvider createPidProvider(String providerName) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + if (!providerType.equals(EZIdDOIProvider.TYPE)) { + // Being asked to create a non-EZId provider + return null; + } + String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); + String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + String identifierGenerationStyle = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE + .lookupOptional(providerName).orElse("randomString"); + String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + + String baseUrl = JvmSettings.EZID_API_URL.lookup(providerName); + String username = JvmSettings.EZID_USERNAME.lookup(providerName); + String password = JvmSettings.EZID_PASSWORD.lookup(providerName); + + return new EZIdDOIProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + managedList, excludedList, baseUrl, username, password); + } + + public String getType() { + return EZIdDOIProvider.TYPE; + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java index 86ad5b567fc..ff840c28148 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java @@ -8,13 +8,16 @@ import java.util.Map; import java.util.logging.Logger; -import jakarta.ejb.Stateless; - public class FakeDOIProvider extends DOIProvider { private static final Logger logger = Logger.getLogger(FakeDOIProvider.class.getCanonicalName()); + static final String TYPE = "FAKE"; + + public FakeDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, + String datafilePidFormat, String managedList, String excludedList) { + super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + } - //Only need to check locally public boolean isGlobalIdUnique(GlobalId globalId) { try { @@ -27,7 +30,7 @@ public boolean isGlobalIdUnique(GlobalId globalId) { @Override public boolean alreadyRegistered(GlobalId globalId, boolean noProviderDefault) { - boolean existsLocally = !dvObjectService.isGlobalIdLocallyUnique(globalId); + boolean existsLocally = !pidProviderService.isGlobalIdLocallyUnique(globalId); return existsLocally ? existsLocally : noProviderDefault; } @@ -84,4 +87,8 @@ public String getName() { return null; } + public static String getType() { + return TYPE; + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java new file mode 100644 index 00000000000..65f0bf8d941 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java @@ -0,0 +1,32 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.util.SystemConfig; + +class FakeProviderFactory implements PidProviderFactory { + + @Override + public PidProvider createPidProvider(String providerName) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + if (!providerType.equals(EZIdDOIProvider.TYPE)) { + // Being asked to create a non-EZId provider + return null; + } + String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); + String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + String identifierGenerationStyle = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE + .lookupOptional(providerName).orElse("randomString"); + String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + + return new FakeDOIProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + managedList, excludedList); + } + + public String getType() { + return FakeDOIProvider.TYPE; + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index f8fbd797604..363d033fd46 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -21,20 +21,14 @@ package edu.harvard.iq.dataverse.pidproviders; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.settings.JvmSettings; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean; - import java.io.File; import java.io.FileInputStream; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; -import jakarta.ejb.EJB; -import jakarta.ejb.Stateless; import java.security.PrivateKey; /* Handlenet imports: */ @@ -66,20 +60,27 @@ */ public class HandlePidProvider extends AbstractPidProvider { - @EJB - DataverseServiceBean dataverseService; - @EJB - SettingsServiceBean settingsService; private static final Logger logger = Logger.getLogger(HandlePidProvider.class.getCanonicalName()); public static final String HDL_PROTOCOL = "hdl"; - int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); public static final String HTTP_HDL_RESOLVER_URL = "http://hdl.handle.net/"; public static final String HDL_RESOLVER_URL = "https://hdl.handle.net/"; - public HandlePidProvider() { - logger.log(Level.FINE,"Constructor"); - configured = true; + int handlenetIndex; + private boolean isIndependentHandleService; + private String authHandle; + private String keyPath; + private String keyPassphrase; + + HandlePidProvider(String authority, String shoulder, String identifierGenerationStyle, + String datafilePidFormat, String managedList, String excludedList, int index, boolean isIndependentService, String authHandle, String path, String passphrase) { + super(HDL_PROTOCOL, authority, shoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + this.handlenetIndex = index; + this.isIndependentHandleService = isIndependentService; + this.authHandle = authHandle; + this.keyPath = path; + this.keyPassphrase = passphrase; + } @Override @@ -234,10 +235,9 @@ private ResolutionRequest buildResolutionRequest(final String handle) { private PublicKeyAuthenticationInfo getAuthInfo(String handlePrefix) { logger.log(Level.FINE,"getAuthInfo"); byte[] key = null; - String adminCredFile = JvmSettings.HANDLENET_KEY_PATH.lookup("handlenet"); - int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); + String adminCredFile = getKeyPath(); - key = readKey(adminCredFile); + key = readKey(adminCredFile); PrivateKey privkey = null; privkey = readPrivKey(key, adminCredFile); String authHandle = getAuthenticationHandle(handlePrefix); @@ -247,8 +247,8 @@ private PublicKeyAuthenticationInfo getAuthInfo(String handlePrefix) { } private String getRegistrationUrl(DvObject dvObject) { logger.log(Level.FINE,"getRegistrationUrl"); - String siteUrl = systemConfig.getDataverseSiteUrl(); - String targetUrl = siteUrl + dvObject.getTargetUrl() + "hdl:" + dvObject.getAuthority() + String siteUrl = SystemConfig.getDataverseSiteUrlStatic(); + String targetUrl = siteUrl + dvObject.getTargetUrl() + "hdl:" + dvObject.getAuthority() + "/" + dvObject.getIdentifier(); return targetUrl; } @@ -281,8 +281,7 @@ private PrivateKey readPrivKey(byte[] key, final String file) { try { byte[] secKey = null; if ( Util.requiresSecretKey(key) ) { - String secret = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup("handlenet"); - secKey = secret.getBytes(StandardCharsets.UTF_8); + secKey = getKeyPassphrase().getBytes(StandardCharsets.UTF_8); } key = Util.decrypt(key, secKey); privkey = Util.getPrivateKeyFromBytes(key, 0); @@ -307,9 +306,9 @@ private String getAuthenticationHandle(DvObject dvObject){ private String getAuthenticationHandle(String handlePrefix) { logger.log(Level.FINE,"getAuthenticationHandle"); - if (systemConfig.getHandleAuthHandle()!=null) { - return systemConfig.getHandleAuthHandle(); - } else if (systemConfig.isIndependentHandleService()) { + if (getHandleAuthHandle()!=null) { + return getHandleAuthHandle(); + } else if (isIndependentHandleService()) { return handlePrefix + "/ADMIN"; } else { return "0.NA/" + handlePrefix; @@ -351,9 +350,8 @@ public void deleteIdentifier(DvObject dvObject) throws Exception { String handle = getDvObjectHandle(dvObject); String authHandle = getAuthenticationHandle(dvObject); - String adminCredFile = JvmSettings.HANDLENET_KEY_PATH.lookup("handlenet"); - int handlenetIndex = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, "handlenet"); - + String adminCredFile = getKeyPath(); + byte[] key = readKey(adminCredFile); PrivateKey privkey = readPrivKey(key, adminCredFile); @@ -459,6 +457,22 @@ public String getName() { // TODO Auto-generated method stub return null; } + + public String getKeyPath() { + return keyPath; + } + + public String getKeyPassphrase() { + return keyPassphrase; + } + + public boolean isIndependentHandleService() { + return isIndependentHandleService; + } + + public String getHandleAuthHandle() { + return authHandle; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java new file mode 100644 index 00000000000..f87ba1c7563 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java @@ -0,0 +1,37 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.util.SystemConfig; + +class HandleProviderFactory implements PidProviderFactory { + + @Override + public PidProvider createPidProvider(String providerName) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + if (!providerType.equals(EZIdDOIProvider.TYPE)) { + // Being asked to create a non-EZId provider + return null; + } + String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); + String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + String identifierGenerationStyle = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE + .lookupOptional(providerName).orElse("randomString"); + String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + + int index = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, providerName); + boolean independentHandleService = JvmSettings.HANDLENET_INDEPENDENT_SERVICE.lookupOptional(Boolean.class, providerName).orElse(false); + String handleAuthHandle = JvmSettings.HANDLENET_AUTH_HANDLE.lookup(providerName); + String path = JvmSettings.HANDLENET_KEY_PATH.lookup(providerName); + String passphrase = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup(providerName); + return new HandlePidProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + managedList, excludedList, index, independentHandleService, handleAuthHandle, path, passphrase); + } + + public String getType() { + return HandlePidProvider.HDL_PROTOCOL; + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 36a0b994ce3..9db29fe9410 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -3,7 +3,6 @@ import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.settings.JvmSettings; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; import edu.harvard.iq.dataverse.util.SystemConfig; import java.util.HashMap; @@ -11,17 +10,17 @@ import java.util.Map; import java.util.logging.Logger; -import jakarta.annotation.PostConstruct; -import jakarta.ejb.Stateless; - /** - * PermaLink provider - * This is a minimalist permanent ID provider intended for use with 'real' datasets/files where the use case none-the-less doesn't lend itself to the use of DOIs or Handles, e.g. - * * due to cost - * * for a catalog/archive where Dataverse has a dataset representing a dataset with DOI/handle stored elsewhere + * PermaLink provider This is a minimalist permanent ID provider intended for + * use with 'real' datasets/files where the use case none-the-less doesn't lend + * itself to the use of DOIs or Handles, e.g. * due to cost * for a + * catalog/archive where Dataverse has a dataset representing a dataset with + * DOI/handle stored elsewhere * - * The initial implementation will mint identifiers locally and will provide the existing page URLs (using the ?persistentID= format). - * This will be overridable by a configurable parameter to support use of an external resolver. + * The initial implementation will mint identifiers locally and will provide the + * existing page URLs (using the ?persistentID= format). This will be + * overridable by a configurable parameter to support use of an external + * resolver. * */ public class PermaLinkPidProvider extends AbstractPidProvider { @@ -31,44 +30,37 @@ public class PermaLinkPidProvider extends AbstractPidProvider { public static final String PERMA_PROTOCOL = "perma"; public static final String PERMA_PROVIDER_NAME = "PERMA"; - //ToDo - handle dataset/file defaults for local system - public static final String PERMA_RESOLVER_URL = JvmSettings.PERMALINK_BASEURL - .lookupOptional("permalink") - .orElse(SystemConfig.getDataverseSiteUrlStatic()); - - String authority = null; + // ToDo - remove + @Deprecated + public static final String PERMA_RESOLVER_URL = JvmSettings.PERMALINK_BASE_URL.lookupOptional("permalink") + .orElse(SystemConfig.getDataverseSiteUrlStatic()); + + String authority = null; private String separator = ""; - - @PostConstruct - private void init() { - if(PERMA_PROTOCOL.equals(settingsService.getValueForKey(Key.Protocol))){ - authority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup("permalink"); - configured=true; - }; - - } - - - //Only used in PidUtilTest - haven't figured out how to mock a PostConstruct call directly - // ToDo - remove after work to allow more than one Pid Provider which is expected to not use stateless beans - public void reInit() { - init(); - } - + + private String baseUrl; + + public PermaLinkPidProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, + String datafilePidFormat, String managedList, String excludedList, String baseUrl) { + super(PERMA_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + managedList, excludedList); + this.baseUrl = baseUrl; + } + @Override public String getSeparator() { - //The perma default + // The perma default return separator; } - + @Override public boolean alreadyRegistered(GlobalId globalId, boolean noProviderDefault) { // Perma doesn't manage registration, so we assume all local PIDs can be treated // as registered - boolean existsLocally = !dvObjectService.isGlobalIdLocallyUnique(globalId); + boolean existsLocally = !pidProviderService.isGlobalIdLocallyUnique(globalId); return existsLocally ? existsLocally : noProviderDefault; } - + @Override public boolean registerWhenPublished() { return false; @@ -76,14 +68,16 @@ public boolean registerWhenPublished() { @Override public List getProviderInformation() { - return List.of(PERMA_PROVIDER_NAME, PERMA_RESOLVER_URL); + return List.of(PERMA_PROVIDER_NAME, getBaseUrl()); } @Override public String createIdentifier(DvObject dvo) throws Throwable { - //Call external resolver and send landing URL? - //FWIW: Return value appears to only be used in RegisterDvObjectCommand where success requires finding the dvo identifier in this string. (Also logged a couple places). - return(dvo.getGlobalId().asString()); + // Call external resolver and send landing URL? + // FWIW: Return value appears to only be used in RegisterDvObjectCommand where + // success requires finding the dvo identifier in this string. (Also logged a + // couple places). + return (dvo.getGlobalId().asString()); } @Override @@ -104,20 +98,20 @@ public void deleteIdentifier(DvObject dvo) throws Exception { @Override public boolean publicizeIdentifier(DvObject dvObject) { - //Generate if needed (i.e. datafile case where we don't create/register early (even with reigsterWhenPublished == false)) - if(dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty() ){ + // Generate if needed (i.e. datafile case where we don't create/register early + // (even with reigsterWhenPublished == false)) + if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { dvObject = generateIdentifier(dvObject); } - //Call external resolver and send landing URL? + // Call external resolver and send landing URL? return true; } @Override public GlobalId parsePersistentId(String pidString) { - //ToDo - handle local PID resolver for dataset/file + // ToDo - handle local PID resolver for dataset/file if (pidString.startsWith(getUrlPrefix())) { - pidString = pidString.replace(getUrlPrefix(), - (PERMA_PROTOCOL + ":")); + pidString = pidString.replace(getUrlPrefix(), (PERMA_PROTOCOL + ":")); } return super.parsePersistentId(pidString); } @@ -140,7 +134,7 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { } return new GlobalId(PERMA_PROTOCOL, authority, identifier, separator, getUrlPrefix(), PERMA_PROVIDER_NAME); } - + @Override public GlobalId parsePersistentId(String protocol, String authority, String identifier) { if (!PERMA_PROTOCOL.equals(protocol)) { @@ -151,10 +145,9 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden @Override public String getUrlPrefix() { - - return PERMA_RESOLVER_URL + "/citation?persistentId=" + PERMA_PROTOCOL + ":"; - } + return getBaseUrl() + "/citation?persistentId=" + PERMA_PROTOCOL + ":"; + } @Override public String getProtocol() { @@ -162,17 +155,19 @@ public String getProtocol() { return null; } - @Override public String getProviderType() { // TODO Auto-generated method stub return null; } - @Override public String getName() { // TODO Auto-generated method stub return null; } + + public String getBaseUrl() { + return baseUrl; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java new file mode 100644 index 00000000000..8b9082ef6ea --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java @@ -0,0 +1,34 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.util.SystemConfig; + +class PermaLinkProviderFactory implements PidProviderFactory { + + @Override + public PidProvider createPidProvider(String providerName) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + if (!providerType.equals(EZIdDOIProvider.TYPE)) { + // Being asked to create a non-EZId provider + return null; + } + String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); + String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + String identifierGenerationStyle = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE + .lookupOptional(providerName).orElse("randomString"); + String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + + String baseUrl = JvmSettings.PERMALINK_BASE_URL.lookupOptional(providerName).orElse(SystemConfig.getDataverseSiteUrlStatic());; + + return new PermaLinkPidProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + managedList, excludedList, baseUrl); + } + + public String getType() { + return FakeDOIProvider.TYPE; + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index 22ee330f855..a359f4f4c00 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -39,7 +39,6 @@ public interface PidProvider { boolean registerWhenPublished(); boolean canManagePID(); - boolean isConfigured(); List getProviderInformation(); @@ -71,6 +70,9 @@ public interface PidProvider { String getProtocol(); String getProviderType(); String getName(); + String getAuthority(); + String getShoulder(); + String getIdentifierGenerationStyle(); //ToDo - now need to get the correct provider based on the protocol, authority, and shoulder (for new pids)/indentifier (for existing pids) @@ -78,7 +80,7 @@ static PidProvider getBean(String protocol, CommandContext ctxt) { final Function protocolHandler = BeanDispatcher.DISPATCHER.get(protocol); if ( protocolHandler != null ) { PidProvider theBean = protocolHandler.apply(ctxt); - if(theBean != null && theBean.isConfigured()) { + if(theBean != null) { logger.fine("getBean returns " + theBean.getProviderInformation().get(0) + " for protocol " + protocol); } return theBean; @@ -188,6 +190,8 @@ static boolean checkDOIAuthority(String doiAuthority){ return true; } + public void setPidProviderServiceBean(PidProviderFactoryBean pidProviderFactoryBean); + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 47a7f08e41e..e43ded52899 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -24,8 +24,14 @@ import jakarta.ejb.EJB; import jakarta.ejb.Singleton; import jakarta.ejb.Startup; -import edu.harvard.iq.dataverse.export.ExportService; +import jakarta.inject.Inject; import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import edu.harvard.iq.dataverse.util.SystemConfig; +import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObjectServiceBean; +import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import io.gdcc.spi.export.Exporter; /** @@ -40,6 +46,18 @@ public class PidProviderFactoryBean { private static final Logger logger = Logger.getLogger(PidProviderFactoryBean.class.getCanonicalName()); + @Inject + DataverseServiceBean dataverseService; + @EJB + protected + SettingsServiceBean settingsService; + @Inject + protected + DvObjectServiceBean dvObjectService; + @Inject + SystemConfig systemConfig; + + private ServiceLoader loader; private Map pidProviderFactoryMap = new HashMap<>(); @@ -103,10 +121,25 @@ private void loadProviders() { String type = JvmSettings.PID_PROVIDER_TYPE.lookup(name); if (pidProviderFactoryMap.containsKey(type)) { PidProvider provider = pidProviderFactoryMap.get(type).createPidProvider(name); + provider.setPidProviderServiceBean(this); PidUtil.addToProviderList(provider); } } PidUtil.addAllToUnmanagedProviderList(Arrays.asList(unmanagedDOISvc, unmanagedHandleSvc)); } + public String getProducer() { + return dataverseService.getRootDataverseName(); + } + + public boolean isGlobalIdLocallyUnique(GlobalId globalId) { + return dvObjectService.isGlobalIdLocallyUnique(globalId); + } + + public String generateNewIdentifierByStoredProcedure() { + return dvObjectService.generateNewIdentifierByStoredProcedure(); + } + + + } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index cc9cc237848..a2c33041b9e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -21,14 +21,13 @@ public class UnmanagedDOIProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(UnmanagedDOIProvider.class.getCanonicalName()); - - @PostConstruct - private void init() { - // Always on - configured = true; + public UnmanagedDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, + String datafilePidFormat) { + super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat); } + private static final Logger logger = Logger.getLogger(UnmanagedDOIProvider.class.getCanonicalName()); + @Override public boolean canManagePID() { return false; @@ -86,7 +85,6 @@ public String getName() { return null; } - // PID recognition // Done by DOIProvider diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java index 60cb089b961..e4b2231b2c9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java @@ -386,7 +386,7 @@ class DataCiteMetadataTemplate { static { try (InputStream in = DataCiteMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { - template = new String(in.readAllBytes(),StandardCharset.UTF_8); + template = new String(in.readAllBytes(),StandardCharsets.UTF_8); } catch (Exception e) { logger.log(Level.SEVERE, "datacite metadata template load error"); logger.log(Level.SEVERE, "String " + e.toString()); diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index 7eaa7e03488..a617409d377 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -98,6 +98,8 @@ public enum JvmSettings { PID_PROVIDER_NAME(SCOPE_PID_PROVIDER, "name"), PID_PROVIDER_AUTHORITY(SCOPE_PID_PROVIDER, "authority"), PID_PROVIDER_SHOULDER(SCOPE_PID_PROVIDER, "shoulder"), + PID_PROVIDER_IDENTIFIER_GENERATION_STYLE(SCOPE_PID_PROVIDER, "identifier-generation-style"), + PID_PROVIDER_DATAFILE_PID_FORMAT(SCOPE_PID_PROVIDER, "datafile-pid-format"), PID_PROVIDER_MANAGED_LIST(SCOPE_PID_PROVIDER, "managed-list"), PID_PROVIDER_EXCLUDED_LIST(SCOPE_PID_PROVIDER, "excluded-list"), @@ -116,11 +118,13 @@ public enum JvmSettings { // PROVIDER PERMALINK SCOPE_PID_PERMALINK(SCOPE_PID_PROVIDER, "permalink"), - PERMALINK_BASEURL(SCOPE_PID_PERMALINK, "base-url"), + PERMALINK_BASE_URL(SCOPE_PID_PERMALINK, "base-url"), // PROVIDER HANDLE SCOPE_PID_HANDLENET(SCOPE_PID_PROVIDER, "handlenet"), HANDLENET_INDEX(SCOPE_PID_HANDLENET, "index"), + HANDLENET_INDEPENDENT_SERVICE(SCOPE_PID_HANDLENET, "independent-service"), + HANDLENET_AUTH_HANDLE(SCOPE_PID_HANDLENET, "auth-handle"), SCOPE_PID_HANDLENET_KEY(SCOPE_PID_HANDLENET, "key"), HANDLENET_KEY_PATH(SCOPE_PID_HANDLENET_KEY, "path"), HANDLENET_KEY_PASSPHRASE(SCOPE_PID_HANDLENET_KEY, "passphrase"), diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java index 3c6992f8ec3..d8736f5ea0a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java @@ -1016,16 +1016,7 @@ public boolean isFilePIDsEnabledForCollection(Dataverse collection) { return thisCollection.getFilePIDsEnabled(); } - public boolean isIndependentHandleService() { - boolean safeDefaultIfKeyNotFound = false; - return settingsService.isTrueForKey(SettingsServiceBean.Key.IndependentHandleService, safeDefaultIfKeyNotFound); - - } - - public String getHandleAuthHandle() { - String handleAuthHandle = settingsService.getValueForKey(SettingsServiceBean.Key.HandleAuthHandle, null); - return handleAuthHandle; - } + public String getMDCLogPath() { String mDCLogPath = settingsService.getValueForKey(SettingsServiceBean.Key.MDCLogPath, null); From d6936fbfe3f71608f745ae9bf4676006ba07fcf5 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:27:06 -0500 Subject: [PATCH 007/113] unmanaged providers --- .../pidproviders/UnmanagedDOIProvider.java | 17 +--- ...n.java => UnmanagedHandlePidProvider.java} | 31 ++++-- .../UnmanagedPermaLinkPidProvider.java | 99 +++++++++++++++++++ 3 files changed, 126 insertions(+), 21 deletions(-) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{UnmanagedHandlenetServiceBean.java => UnmanagedHandlePidProvider.java} (80%) create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index a2c33041b9e..882b3cbf461 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -3,11 +3,6 @@ import java.io.IOException; import java.util.List; import java.util.Map; -import java.util.logging.Logger; - -import jakarta.annotation.PostConstruct; -import jakarta.ejb.Stateless; - import org.apache.commons.httpclient.HttpException; import org.apache.commons.lang3.NotImplementedException; @@ -21,13 +16,13 @@ public class UnmanagedDOIProvider extends DOIProvider { + private static final String NAME = "UnmanagedDOIProvider"; + public UnmanagedDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat) { - super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat); + super(NAME); } - private static final Logger logger = Logger.getLogger(UnmanagedDOIProvider.class.getCanonicalName()); - @Override public boolean canManagePID() { return false; @@ -75,14 +70,12 @@ public List getProviderInformation() { @Override public String getProviderType() { - // TODO Auto-generated method stub - return null; + return "unamagedDOI"; } @Override public String getName() { - // TODO Auto-generated method stub - return null; + return NAME; } // PID recognition diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java similarity index 80% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java index 245cc11f4cd..7ed59022959 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlenetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java @@ -9,18 +9,22 @@ import jakarta.ejb.Stateless; import org.apache.commons.lang3.NotImplementedException; -/** This class is just used to parse Handles that are not managed by any account configured in Dataverse - * It does not implement any of the methods related to PID CRUD +/** + * This class is just used to parse Handles that are not managed by any account + * configured in Dataverse It does not implement any of the methods related to + * PID CRUD * */ -@Stateless -public class UnmanagedHandlenetServiceBean extends AbstractPidProvider { - private static final Logger logger = Logger.getLogger(UnmanagedHandlenetServiceBean.class.getCanonicalName()); +public class UnmanagedHandlePidProvider extends AbstractPidProvider { - public UnmanagedHandlenetServiceBean() { + private static final Logger logger = Logger.getLogger(UnmanagedHandlePidProvider.class.getCanonicalName()); + private static final String NAME = "UnmanagedHandleProvider"; + + public UnmanagedHandlePidProvider() { + super(NAME, HandlePidProvider.HDL_PROTOCOL); logger.log(Level.FINE, "Constructor"); - configured = true; + } @Override @@ -71,8 +75,7 @@ public boolean publicizeIdentifier(DvObject dvObject) { @Override public GlobalId parsePersistentId(String pidString) { if (pidString.startsWith(HandlePidProvider.HDL_RESOLVER_URL)) { - pidString = pidString.replace(HandlePidProvider.HDL_RESOLVER_URL, - (HandlePidProvider.HDL_PROTOCOL + ":")); + pidString = pidString.replace(HandlePidProvider.HDL_RESOLVER_URL, (HandlePidProvider.HDL_PROTOCOL + ":")); } else if (pidString.startsWith(HandlePidProvider.HTTP_HDL_RESOLVER_URL)) { pidString = pidString.replace(HandlePidProvider.HTTP_HDL_RESOLVER_URL, (HandlePidProvider.HDL_PROTOCOL + ":")); @@ -101,4 +104,14 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden public String getUrlPrefix() { return HandlePidProvider.HDL_RESOLVER_URL; } + + @Override + public String getProviderType() { + return "unamagedHandle"; + } + + @Override + public String getName() { + return NAME; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java new file mode 100644 index 00000000000..5250cd959f9 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java @@ -0,0 +1,99 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.util.SystemConfig; + +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import jakarta.ejb.Stateless; +import org.apache.commons.lang3.NotImplementedException; + +/** This class is just used to parse Handles that are not managed by any account configured in Dataverse + * It does not implement any of the methods related to PID CRUD + * + */ +@Stateless +public class UnmanagedPermaLinkPidProvider extends AbstractPidProvider { + + private static final Logger logger = Logger.getLogger(UnmanagedPermaLinkPidProvider.class.getCanonicalName()); + private static final String NAME = "UnmanagedPermaLinkProvider"; + + public UnmanagedPermaLinkPidProvider() { + super(NAME, PermaLinkPidProvider.PERMA_PROTOCOL); + logger.log(Level.FINE, "Constructor"); + } + + @Override + public boolean canManagePID() { + return false; + } + + @Override + public boolean registerWhenPublished() { + throw new NotImplementedException(); + } + + @Override + public boolean alreadyRegistered(GlobalId pid, boolean noProviderDefault) throws Exception { + throw new NotImplementedException(); + } + + @Override + public Map getIdentifierMetadata(DvObject dvObject) { + throw new NotImplementedException(); + } + + @Override + public String modifyIdentifierTargetURL(DvObject dvObject) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void deleteIdentifier(DvObject dvObject) throws Exception { + throw new NotImplementedException(); + } + + @Override + public List getProviderInformation() { + return List.of("UnmanagedPermaLink", ""); + } + + @Override + public String createIdentifier(DvObject dvObject) throws Throwable { + throw new NotImplementedException(); + } + + @Override + public boolean publicizeIdentifier(DvObject dvObject) { + throw new NotImplementedException(); + } + + @Override + public GlobalId parsePersistentId(String protocol, String identifierString) { + if (!PermaLinkPidProvider.PERMA_PROTOCOL.equals(protocol)) { + return null; + } + GlobalId globalId = super.parsePersistentId(protocol, identifierString); + return globalId; + } + + @Override + public GlobalId parsePersistentId(String protocol, String authority, String identifier) { + if (!PermaLinkPidProvider.PERMA_PROTOCOL.equals(protocol)) { + return null; + } + return super.parsePersistentId(protocol, authority, identifier); + } + + @Override + public String getUrlPrefix() { + return SystemConfig.getDataverseSiteUrlStatic()+ "/citation?persistentId=" + PermaLinkPidProvider.PERMA_PROTOCOL + ":"; + } + + @Override + public String getProviderType() { + return PermaLinkPidProvider.TYPE; + } +} From ad0789219db13a4627cd3f4ad4e71518d455eeee Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:28:17 -0500 Subject: [PATCH 008/113] add getters --- .../edu/harvard/iq/dataverse/pidproviders/PidProvider.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index a359f4f4c00..f34a9f20fb3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -192,6 +192,12 @@ static boolean checkDOIAuthority(String doiAuthority){ public void setPidProviderServiceBean(PidProviderFactoryBean pidProviderFactoryBean); + String getDatafilePidFormat(); + + Set getManagedSet(); + + Set getExcludedSet(); + } From e31a5aea819c442525f827f299f9848636c5205c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:29:16 -0500 Subject: [PATCH 009/113] add name to cnstr, add cnstr for unmanaged, add auth/shoulder checks --- .../pidproviders/AbstractPidProvider.java | 68 ++++++++++++++----- .../dataverse/pidproviders/DOIProvider.java | 9 ++- .../pidproviders/DataCiteDOIProvider.java | 35 ++++++++-- .../pidproviders/DataCiteProviderFactory.java | 2 +- .../pidproviders/EZIdDOIProvider.java | 4 +- .../pidproviders/EZIdProviderFactory.java | 2 +- .../pidproviders/FakeDOIProvider.java | 17 +---- .../pidproviders/FakeProviderFactory.java | 6 +- .../pidproviders/HandlePidProvider.java | 19 ++---- .../pidproviders/HandleProviderFactory.java | 14 ++-- 10 files changed, 112 insertions(+), 64 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index bf4a8e9c7de..3c3005628d0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -31,26 +31,37 @@ public abstract class AbstractPidProvider implements PidProvider { private String protocol; - private String authority; + private String authority = null; - private String shoulder; + private String shoulder = null; - private String identifierGenerationStyle; + private String identifierGenerationStyle = null; - private String datafilePidFormat; + private String datafilePidFormat = null; - private List managedList; + private HashSet managedSet; - private List excludedList; + private HashSet excludedSet; + + private String name; + + AbstractPidProvider(String name, String protocol) + { + this.name = name; + this.protocol = protocol; + this.managedSet = new HashSet(); + this.excludedSet = new HashSet(); + } - AbstractPidProvider(String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + AbstractPidProvider(String name, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + this.name = name; this.protocol = protocol; this.authority = authority; this.shoulder = shoulder; this.identifierGenerationStyle = identifierGenerationStyle; this.datafilePidFormat = datafilePidFormat; - this.managedList = Arrays.asList(managedList.split(",\\s")); - this.excludedList = Arrays.asList(excludedList.split(",\\s")); + this.managedSet = new HashSet(Arrays.asList(managedList.split(",\\s"))); + this.excludedSet = new HashSet(Arrays.asList(excludedList.split(",\\s"))); } @@ -259,13 +270,14 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { if (identifierString == null) { return null; } - int index = identifierString.indexOf('/'); + int index = identifierString.indexOf(getSeparator()); if (index > 0 && (index + 1) < identifierString.length()) { // '/' found with one or more characters // before and after it // Strip any whitespace, ; and ' from authority (should finding them cause a // failure instead?) authority = PidProvider.formatIdentifierString(identifierString.substring(0, index)); + if (PidProvider.testforNullTerminator(authority)) { return null; } @@ -273,8 +285,23 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { if (PidProvider.testforNullTerminator(identifier)) { return null; } - ToDo - test specific authority/shoulder and against managed and excluded lists (should be maps?) - add unmanagedPermaProvider? + //Check authority/identifier if this is a provider that manages specific identifiers + // /is not one of the unmanaged providers that has null authority + if (getAuthority() != null) { + + String cleanIdentifier = authority + getSeparator() + identifier; + /* + * Test if this provider manages this identifier - return null if it does not It + * does if ((the identifier's authority and shoulder match the provider's), or + * the identifier in on the managed set), and the identifier is not in the + * excluded set. + */ + if (!(((authority.equals(getAuthority()) && identifier.startsWith(getShoulder())) + || getManagedSet().contains(cleanIdentifier)) && !getExcludedSet().contains(cleanIdentifier))) { + return null; + } + } + } else { logger.log(Level.INFO, "Error parsing identifier: {0}: '':/'' not found in string", identifierString); @@ -725,16 +752,23 @@ public String getIdentifierGenerationStyle() { return identifierGenerationStyle; } + @Override public String getDatafilePidFormat() { return datafilePidFormat; } - public List getManagedList() { - return managedList; + @Override + public Set getManagedSet() { + return managedSet; } - public List getExcludedList() { - return excludedList; + @Override + public Set getExcludedSet() { + return excludedSet; + } + + @Override + public String getName() { + return name; } - } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java index cfdff3c3f51..50d5510b0ce 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java @@ -11,8 +11,13 @@ public abstract class DOIProvider extends AbstractPidProvider { public static final String DXDOI_RESOLVER_URL = "https://dx.doi.org/"; public static final String HTTP_DXDOI_RESOLVER_URL = "http://dx.doi.org/"; - public DOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { - super(DOI_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + public DOIProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + super(name, DOI_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + } + + //For Unmanged provider + public DOIProvider(String name) { + super(name, DOI_PROTOCOL); } @Override diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index a15e60238ff..d7fcad24496 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -38,12 +38,20 @@ public class DataCiteDOIProvider extends DOIProvider { @EJB DOIDataCiteRegisterService doiDataCiteRegisterService; - public DataCiteDOIProvider(String providerAuthority, String providerShoulder, String managedList, - String excludedList, String mdsUrl, String apiUrl, String username, String password, - String identifierGenerationStyle, String datafilePidFormat) { - super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, + private String mdsUrl; + private String apiUrl; + private String username; + private String password; + + public DataCiteDOIProvider(String name, String providerAuthority, String providerShoulder, String managedList, + String excludedList, String identifierGenerationStyle, String datafilePidFormat, String mdsUrl, + String apiUrl, String username, String password) { + super(name, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); - // TODO Auto-generated constructor stub + this.mdsUrl = mdsUrl; + this.apiUrl = apiUrl; + this.username = username; + this.password = password; } @Override @@ -268,4 +276,21 @@ public String getName() { // TODO Auto-generated method stub return null; } + + public String getMdsUrl() { + return mdsUrl; + } + + public String getApiUrl() { + return apiUrl; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index d35354dc5fd..bce9bed45ea 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -25,7 +25,7 @@ public PidProvider createPidProvider(String providerName) { String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); - return new DataCiteDOIProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); + return new DataCiteDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); } public String getType() { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java index 4147815b5bf..f2761aa7186 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java @@ -30,9 +30,9 @@ public class EZIdDOIProvider extends DOIProvider { private String baseUrl; - public EZIdDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, + public EZIdDOIProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, String baseUrl, String username, String password) { - super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + super(name, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); // Creating the service doesn't do any harm, just initializing some object data here. // Makes sure we don't run into NPEs from the other methods, but will obviously fail if the // login below does not work. diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java index 26b3ada437e..0f6224afaab 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java @@ -25,7 +25,7 @@ public PidProvider createPidProvider(String providerName) { String username = JvmSettings.EZID_USERNAME.lookup(providerName); String password = JvmSettings.EZID_PASSWORD.lookup(providerName); - return new EZIdDOIProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + return new EZIdDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, baseUrl, username, password); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java index ff840c28148..65dbcff0a47 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java @@ -6,16 +6,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Logger; public class FakeDOIProvider extends DOIProvider { - private static final Logger logger = Logger.getLogger(FakeDOIProvider.class.getCanonicalName()); static final String TYPE = "FAKE"; - public FakeDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, + public FakeDOIProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { - super(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + super(name, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } //Only need to check locally @@ -77,17 +75,6 @@ protected String getProviderKeyName() { @Override public String getProviderType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - - public static String getType() { return TYPE; } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java index 65f0bf8d941..65e77c00c8c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java @@ -8,7 +8,7 @@ class FakeProviderFactory implements PidProviderFactory { @Override public PidProvider createPidProvider(String providerName) { String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); - if (!providerType.equals(EZIdDOIProvider.TYPE)) { + if (!providerType.equals(FakeDOIProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } @@ -21,8 +21,8 @@ public PidProvider createPidProvider(String providerName) { String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); - return new FakeDOIProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, - managedList, excludedList); + return new FakeDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + datafilePidFormat, managedList, excludedList); } public String getType() { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index 363d033fd46..1070583c43f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -63,8 +63,11 @@ public class HandlePidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(HandlePidProvider.class.getCanonicalName()); public static final String HDL_PROTOCOL = "hdl"; + public static final String TYPE = "hdl"; public static final String HTTP_HDL_RESOLVER_URL = "http://hdl.handle.net/"; public static final String HDL_RESOLVER_URL = "https://hdl.handle.net/"; + + int handlenetIndex; private boolean isIndependentHandleService; @@ -72,9 +75,9 @@ public class HandlePidProvider extends AbstractPidProvider { private String keyPath; private String keyPassphrase; - HandlePidProvider(String authority, String shoulder, String identifierGenerationStyle, + HandlePidProvider(String name, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, int index, boolean isIndependentService, String authHandle, String path, String passphrase) { - super(HDL_PROTOCOL, authority, shoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + super(name, HDL_PROTOCOL, authority, shoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.handlenetIndex = index; this.isIndependentHandleService = isIndependentService; this.authHandle = authHandle; @@ -442,20 +445,12 @@ public String getUrlPrefix() { @Override public String getProtocol() { - // TODO Auto-generated method stub - return null; + return HDL_PROTOCOL; } @Override public String getProviderType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; + return TYPE; } public String getKeyPath() { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java index f87ba1c7563..8e5a1aef4cb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java @@ -8,7 +8,7 @@ class HandleProviderFactory implements PidProviderFactory { @Override public PidProvider createPidProvider(String providerName) { String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); - if (!providerType.equals(EZIdDOIProvider.TYPE)) { + if (!providerType.equals(HandlePidProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } @@ -20,18 +20,20 @@ public PidProvider createPidProvider(String providerName) { .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); - + int index = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, providerName); - boolean independentHandleService = JvmSettings.HANDLENET_INDEPENDENT_SERVICE.lookupOptional(Boolean.class, providerName).orElse(false); + boolean independentHandleService = JvmSettings.HANDLENET_INDEPENDENT_SERVICE + .lookupOptional(Boolean.class, providerName).orElse(false); String handleAuthHandle = JvmSettings.HANDLENET_AUTH_HANDLE.lookup(providerName); String path = JvmSettings.HANDLENET_KEY_PATH.lookup(providerName); String passphrase = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup(providerName); - return new HandlePidProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, - managedList, excludedList, index, independentHandleService, handleAuthHandle, path, passphrase); + return new HandlePidProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + datafilePidFormat, managedList, excludedList, index, independentHandleService, handleAuthHandle, path, + passphrase); } public String getType() { - return HandlePidProvider.HDL_PROTOCOL; + return HandlePidProvider.TYPE; } } From a8590eaf1fbf2051481a7e26d7d148af52178478 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:29:41 -0500 Subject: [PATCH 010/113] update permalinks, add separator setting --- .../pidproviders/PermaLinkPidProvider.java | 25 ++++++++----------- .../PermaLinkProviderFactory.java | 15 ++++++----- .../iq/dataverse/settings/JvmSettings.java | 1 + 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 9db29fe9410..a7c5c5b559c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -28,6 +28,7 @@ public class PermaLinkPidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(PermaLinkPidProvider.class.getCanonicalName()); public static final String PERMA_PROTOCOL = "perma"; + public static final String TYPE = "perma"; public static final String PERMA_PROVIDER_NAME = "PERMA"; // ToDo - remove @@ -35,21 +36,23 @@ public class PermaLinkPidProvider extends AbstractPidProvider { public static final String PERMA_RESOLVER_URL = JvmSettings.PERMALINK_BASE_URL.lookupOptional("permalink") .orElse(SystemConfig.getDataverseSiteUrlStatic()); + + String authority = null; private String separator = ""; private String baseUrl; - public PermaLinkPidProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, - String datafilePidFormat, String managedList, String excludedList, String baseUrl) { - super(PERMA_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + public PermaLinkPidProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, + String datafilePidFormat, String managedList, String excludedList, String baseUrl, String separator) { + super(name, PERMA_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.baseUrl = baseUrl; + this.separator = separator; } @Override public String getSeparator() { - // The perma default return separator; } @@ -99,7 +102,7 @@ public void deleteIdentifier(DvObject dvo) throws Exception { @Override public boolean publicizeIdentifier(DvObject dvObject) { // Generate if needed (i.e. datafile case where we don't create/register early - // (even with reigsterWhenPublished == false)) + // (even with registerWhenPublished == false)) if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { dvObject = generateIdentifier(dvObject); } @@ -151,20 +154,12 @@ public String getUrlPrefix() { @Override public String getProtocol() { - // TODO Auto-generated method stub - return null; + return PERMA_PROTOCOL; } @Override public String getProviderType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; + return PERMA_PROTOCOL; } public String getBaseUrl() { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java index 8b9082ef6ea..95852f03232 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java @@ -8,7 +8,7 @@ class PermaLinkProviderFactory implements PidProviderFactory { @Override public PidProvider createPidProvider(String providerName) { String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); - if (!providerType.equals(EZIdDOIProvider.TYPE)) { + if (!providerType.equals(PermaLinkPidProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } @@ -20,15 +20,18 @@ public PidProvider createPidProvider(String providerName) { .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); - - String baseUrl = JvmSettings.PERMALINK_BASE_URL.lookupOptional(providerName).orElse(SystemConfig.getDataverseSiteUrlStatic());; - return new PermaLinkPidProvider(providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, - managedList, excludedList, baseUrl); + String baseUrl = JvmSettings.PERMALINK_BASE_URL.lookupOptional(providerName) + .orElse(SystemConfig.getDataverseSiteUrlStatic()); + ; + String separator = JvmSettings.PERMALINK_SEPARATOR.lookupOptional(providerName).orElse(""); + + return new PermaLinkPidProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + datafilePidFormat, managedList, excludedList, baseUrl, separator); } public String getType() { - return FakeDOIProvider.TYPE; + return PermaLinkPidProvider.TYPE; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index a617409d377..4ee194c6fa3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -119,6 +119,7 @@ public enum JvmSettings { // PROVIDER PERMALINK SCOPE_PID_PERMALINK(SCOPE_PID_PROVIDER, "permalink"), PERMALINK_BASE_URL(SCOPE_PID_PERMALINK, "base-url"), + PERMALINK_SEPARATOR(SCOPE_PID_PERMALINK, "separator"), // PROVIDER HANDLE SCOPE_PID_HANDLENET(SCOPE_PID_PROVIDER, "handlenet"), From 4011e6364da82880122fcb7e5ea65020d8d93cdf Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:35:27 -0500 Subject: [PATCH 011/113] no arg constructor --- .../iq/dataverse/pidproviders/UnmanagedDOIProvider.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index 882b3cbf461..f779ed77050 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -18,8 +18,7 @@ public class UnmanagedDOIProvider extends DOIProvider { private static final String NAME = "UnmanagedDOIProvider"; - public UnmanagedDOIProvider(String providerAuthority, String providerShoulder, String identifierGenerationStyle, - String datafilePidFormat) { + public UnmanagedDOIProvider() { super(NAME); } From 77c63bbbb2aea25fea2e02351ca903cc0d43999a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:35:42 -0500 Subject: [PATCH 012/113] add unmanaged providers --- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index e43ded52899..8e4251d10cc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -125,7 +125,7 @@ private void loadProviders() { PidUtil.addToProviderList(provider); } } - PidUtil.addAllToUnmanagedProviderList(Arrays.asList(unmanagedDOISvc, unmanagedHandleSvc)); + PidUtil.addAllToUnmanagedProviderList(Arrays.asList(new UnmanagedDOIProvider(), new UnmanagedHandlePidProvider(), new UnmanagedPermaLinkPidProvider())); } public String getProducer() { From 3b2e88bd2b2c4d8746c95c5a104c6a53392b91b9 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 4 Jan 2024 15:35:59 -0500 Subject: [PATCH 013/113] check canManagePid instead --- .../dataverse/engine/command/impl/CreateNewDatasetCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java index 4b5d46f94e3..306276a8339 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java @@ -89,7 +89,7 @@ protected DatasetVersion getVersionToPersist( Dataset theDataset ) { @Override protected void handlePid(Dataset theDataset, CommandContext ctxt) throws CommandException { PidProvider idServiceBean = PidProvider.getBean(ctxt); - if(!idServiceBean.isConfigured()) { + if(!idServiceBean.canManagePID()) { throw new IllegalCommandException("PID Provider " + idServiceBean.getProviderInformation().get(0) + " is not configured.", this); } if ( !idServiceBean.registerWhenPublished() ) { From e94c936d7b4d483148ed445b37ad69b0be81d0fe Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 10:39:07 -0500 Subject: [PATCH 014/113] replace getBean(), compiles except for tests --- .../iq/dataverse/DataFileServiceBean.java | 5 +- .../edu/harvard/iq/dataverse/DatasetPage.java | 6 +- .../iq/dataverse/DatasetServiceBean.java | 12 ++-- .../iq/dataverse/EjbDataverseEngine.java | 39 ++----------- .../edu/harvard/iq/dataverse/GlobalId.java | 2 +- .../iq/dataverse/S3PackageImporter.java | 11 ++-- .../importer/filesystem/FileRecordWriter.java | 10 ++-- .../engine/command/CommandContext.java | 16 +----- .../impl/AbstractCreateDatasetCommand.java | 7 ++- .../command/impl/AbstractDatasetCommand.java | 15 ++--- .../command/impl/CreateNewDatasetCommand.java | 13 +++-- .../command/impl/DeleteDataFileCommand.java | 19 ++++--- .../engine/command/impl/DeletePidCommand.java | 8 +-- .../command/impl/DestroyDatasetCommand.java | 23 +++++--- .../FinalizeDatasetPublicationCommand.java | 14 +++-- .../command/impl/ImportDatasetCommand.java | 6 +- .../command/impl/RegisterDvObjectCommand.java | 28 ++++----- .../command/impl/ReservePidCommand.java | 8 +-- .../impl/UpdateDatasetTargetURLCommand.java | 7 ++- .../UpdateDvObjectPIDMetadataCommand.java | 7 ++- .../dataverse/pidproviders/PidProvider.java | 57 ------------------- .../pidproviders/PidProviderFactoryBean.java | 42 ++++++++++---- .../iq/dataverse/pidproviders/PidUtil.java | 49 +++++++++++++++- 23 files changed, 192 insertions(+), 212 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java index c9d50bbed9d..8ceb529a5d4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java @@ -1242,9 +1242,8 @@ public List selectFilesWithMissingOriginalSizes() { * Check that a identifier entered by the user is unique (not currently used * for any other study in this Dataverse Network). Also check for duplicate * in the remote PID service if needed - * @param userIdentifier - * @param datafile - * @param idServiceBean + * @param datafileId + * @param storageLocation * @return {@code true} iff the global identifier is unique. */ public void finalizeFileDelete(Long dataFileId, String storageLocation) throws IOException { diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 04409ceb400..2547682a119 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -2120,9 +2120,9 @@ private String init(boolean initFull) { //Wait until the create command before actually getting an identifier, except if we're using directUpload //Need to assign an identifier prior to calls to requestDirectUploadUrl if direct upload is used. if ( isEmpty(dataset.getIdentifier()) && systemConfig.directUploadEnabled(dataset) ) { - CommandContext ctxt = commandEngine.getContext(); - PidProvider idServiceBean = PidProvider.getBean(ctxt); - dataset.setIdentifier(idServiceBean.generateDatasetIdentifier(dataset)); + CommandContext ctxt = commandEngine.getContext(); + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(dataset); + dataset.setIdentifier(pidProvider.generateDatasetIdentifier(dataset)); } dataverseTemplates.addAll(dataverseService.find(ownerId).getTemplates()); if (!dataverseService.find(ownerId).isTemplateRoot()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java index 0aedc082eca..35a4c04e6cd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java @@ -20,6 +20,7 @@ import edu.harvard.iq.dataverse.globus.GlobusServiceBean; import edu.harvard.iq.dataverse.harvest.server.OAIRecordServiceBean; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; @@ -955,10 +956,11 @@ the changes from file ingest (which may be happening in parallel, also they can be run in sequence). -- L.A. Mar. 2018 */ @Asynchronous + @Deprecated public void obtainPersistentIdentifiersForDatafiles(Dataset dataset) { - PidProvider idServiceBean = PidProvider.getBean(dataset.getProtocol(), commandEngine.getContext()); + PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderName()); - //If the Id type is sequential and Dependent then write file idenitifiers outside the command + //If the Id type is sequential and Dependent then write file identifiers outside the command String datasetIdentifier = dataset.getIdentifier(); Long maxIdentifier = null; @@ -977,7 +979,7 @@ public void obtainPersistentIdentifiersForDatafiles(Dataset dataset) { maxIdentifier++; datafile.setIdentifier(datasetIdentifier + "/" + maxIdentifier.toString()); } else { - datafile.setIdentifier(idServiceBean.generateDataFileIdentifier(datafile)); + datafile.setIdentifier(pidProvider.generateDataFileIdentifier(datafile)); } if (datafile.getProtocol() == null) { @@ -993,14 +995,14 @@ public void obtainPersistentIdentifiersForDatafiles(Dataset dataset) { try { logger.log(Level.FINE, "creating identifier"); - doiRetString = idServiceBean.createIdentifier(datafile); + doiRetString = pidProvider.createIdentifier(datafile); } catch (Throwable e) { logger.log(Level.WARNING, "Exception while creating Identifier: " + e.getMessage(), e); doiRetString = ""; } // Check return value to make sure registration succeeded - if (!idServiceBean.registerWhenPublished() && doiRetString.contains(datafile.getIdentifier())) { + if (!pidProvider.registerWhenPublished() && doiRetString.contains(datafile.getIdentifier())) { datafile.setIdentifierRegistered(true); datafile.setGlobalIdCreateTime(new Date()); } diff --git a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java index a5a16f1ba03..b68743a15f8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java +++ b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java @@ -22,6 +22,7 @@ import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -117,20 +118,8 @@ public class EjbDataverseEngine { DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels; @EJB - EZIdDOIProvider doiEZId; - - @EJB - DataCiteDOIProvider doiDataCite; + PidProviderFactoryBean pidProviderFactory; - @EJB - FakeDOIProvider fakePidProvider; - - @EJB - HandlePidProvider handleNet; - - @EJB - PermaLinkPidProvider permaLinkProvider; - @EJB SettingsServiceBean settings; @@ -487,28 +476,8 @@ public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels() { } @Override - public EZIdDOIProvider doiEZId() { - return doiEZId; - } - - @Override - public DataCiteDOIProvider doiDataCite() { - return doiDataCite; - } - - @Override - public FakeDOIProvider fakePidProvider() { - return fakePidProvider; - } - - @Override - public HandlePidProvider handleNet() { - return handleNet; - } - - @Override - public PermaLinkPidProvider permaLinkProvider() { - return permaLinkProvider; + public PidProviderFactoryBean pidProviderFactory() { + return pidProviderFactory; } @Override diff --git a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java index 182e3ee7f4f..fea0b1140dc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java +++ b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java @@ -67,7 +67,7 @@ public String getIdentifier() { return identifier; } - public String getProvider() { + public String getProviderName() { return managingProviderName; } diff --git a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java index d05e3d6f1db..4f275daefdc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java @@ -204,10 +204,9 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t fmd.setDatasetVersion(dataset.getLatestVersion()); FileUtil.generateS3PackageStorageIdentifier(packageFile); - - PidProvider idServiceBean = PidProvider.getBean(packageFile.getProtocol(), commandEngine.getContext()); + PidProvider pidProvider = commandEngine.getContext().pidProviderFactory().getPidProvider(dataset); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { - String packageIdentifier = idServiceBean.generateDataFileIdentifier(packageFile); + String packageIdentifier = pidProvider.generateDataFileIdentifier(packageFile); packageFile.setIdentifier(packageIdentifier); } @@ -224,15 +223,15 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t if (!packageFile.isIdentifierRegistered()) { String doiRetString = ""; - idServiceBean = PidProvider.getBean(commandEngine.getContext()); + pidProvider = commandEngine.getContext().pidProviderFactory().getPidProvider(dataset); try { - doiRetString = idServiceBean.createIdentifier(packageFile); + doiRetString = pidProvider.createIdentifier(packageFile); } catch (Throwable e) { } // Check return value to make sure registration succeeded - if (!idServiceBean.registerWhenPublished() && doiRetString.contains(packageFile.getIdentifier())) { + if (!pidProvider.registerWhenPublished() && doiRetString.contains(packageFile.getIdentifier())) { packageFile.setIdentifierRegistered(true); packageFile.setGlobalIdCreateTime(new Date()); } diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java index 4f565f70d9e..0588fc76b1c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java @@ -360,9 +360,9 @@ private DataFile createPackageDataFile(List files) { if (commandEngine.getContext().systemConfig().isFilePIDsEnabledForCollection(dataset.getOwner())) { - PidProvider idServiceBean = PidProvider.getBean(packageFile.getProtocol(), commandEngine.getContext()); + PidProvider pidProvider = commandEngine.getContext().pidProviderFactory().getPidProvider(packageFile); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { - packageFile.setIdentifier(idServiceBean.generateDataFileIdentifier(packageFile)); + packageFile.setIdentifier(pidProvider.generateDataFileIdentifier(packageFile)); } String nonNullDefaultIfKeyNotFound = ""; String protocol = commandEngine.getContext().settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); @@ -376,15 +376,15 @@ private DataFile createPackageDataFile(List files) { if (!packageFile.isIdentifierRegistered()) { String doiRetString = ""; - idServiceBean = PidProvider.getBean(commandEngine.getContext()); + try { - doiRetString = idServiceBean.createIdentifier(packageFile); + doiRetString = pidProvider.createIdentifier(packageFile); } catch (Throwable e) { } // Check return value to make sure registration succeeded - if (!idServiceBean.registerWhenPublished() && doiRetString.contains(packageFile.getIdentifier())) { + if (!pidProvider.registerWhenPublished() && doiRetString.contains(packageFile.getIdentifier())) { packageFile.setIdentifierRegistered(true); packageFile.setGlobalIdCreateTime(new Date()); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java index 8447bf7a146..6c4d63e3e35 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java @@ -29,11 +29,7 @@ import edu.harvard.iq.dataverse.datacapturemodule.DataCaptureModuleServiceBean; import edu.harvard.iq.dataverse.engine.DataverseEngine; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.EZIdDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.SolrIndexServiceBean; @@ -100,15 +96,7 @@ public interface CommandContext { public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels(); - public EZIdDOIProvider doiEZId(); - - public DataCiteDOIProvider doiDataCite(); - - public FakeDOIProvider fakePidProvider(); - - public HandlePidProvider handleNet(); - - public PermaLinkPidProvider permaLinkProvider(); + public PidProviderFactoryBean pidProviderFactory(); public GuestbookServiceBean guestbooks(); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index f847b7e6243..5e6869df7d8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -82,9 +82,10 @@ public Dataset execute(CommandContext ctxt) throws CommandException { additionalParameterTests(ctxt); Dataset theDataset = getDataset(); - PidProvider idServiceBean = PidProvider.getBean(ctxt); + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(theDataset); + if ( isEmpty(theDataset.getIdentifier()) ) { - theDataset.setIdentifier(idServiceBean.generateDatasetIdentifier(theDataset)); + theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); } DatasetVersion dsv = getVersionToPersist(theDataset); @@ -118,7 +119,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { theDataset.setStorageIdentifier(driverId + DataAccess.SEPARATOR + theDataset.getAuthorityForFileStorage() + "/" + theDataset.getIdentifierForFileStorage()); } if (theDataset.getIdentifier()==null) { - theDataset.setIdentifier(idServiceBean.generateDatasetIdentifier(theDataset)); + theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); } // Attempt the registration if importing dataset through the API, or the app (but not harvest) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java index fea3bd3387e..a06720f2612 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java @@ -14,6 +14,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.util.BundleUtil; import java.sql.Timestamp; @@ -152,18 +153,18 @@ protected void validateOrDie(DatasetVersion dsv, Boolean lenient) throws Command */ protected void registerExternalIdentifier(Dataset theDataset, CommandContext ctxt, boolean retry) throws CommandException { if (!theDataset.isIdentifierRegistered()) { - PidProvider globalIdServiceBean = PidProvider.getBean(theDataset.getProtocol(), ctxt); - if ( globalIdServiceBean != null ) { + PidProvider pidProvider = PidUtil.getPidProvider(theDataset.getGlobalId().getProviderName()); + if ( pidProvider != null ) { try { - if (globalIdServiceBean.alreadyRegistered(theDataset)) { + if (pidProvider.alreadyRegistered(theDataset)) { int attempts = 0; if(retry) { do { - theDataset.setIdentifier(globalIdServiceBean.generateDatasetIdentifier(theDataset)); + theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); logger.log(Level.INFO, "Attempting to register external identifier for dataset {0} (trying: {1}).", new Object[]{theDataset.getId(), theDataset.getIdentifier()}); attempts++; - } while (globalIdServiceBean.alreadyRegistered(theDataset) && attempts <= FOOLPROOF_RETRIAL_ATTEMPTS_LIMIT); + } while (pidProvider.alreadyRegistered(theDataset) && attempts <= FOOLPROOF_RETRIAL_ATTEMPTS_LIMIT); } if(!retry) { logger.warning("Reserving PID for: " + getDataset().getId() + " during publication failed."); @@ -177,7 +178,7 @@ protected void registerExternalIdentifier(Dataset theDataset, CommandContext ctx } // Invariant: Dataset identifier does not exist in the remote registry try { - globalIdServiceBean.createIdentifier(theDataset); + pidProvider.createIdentifier(theDataset); theDataset.setGlobalIdCreateTime(getTimestamp()); theDataset.setIdentifierRegistered(true); } catch (Throwable ex) { @@ -185,7 +186,7 @@ protected void registerExternalIdentifier(Dataset theDataset, CommandContext ctx } } catch (Throwable e) { - throw new CommandException(BundleUtil.getStringFromBundle("dataset.publish.error", globalIdServiceBean.getProviderInformation()), this); + throw new CommandException(BundleUtil.getStringFromBundle("dataset.publish.error", pidProvider.getProviderInformation()), this); } } else { throw new IllegalCommandException("This dataset may not be published because its id registry service is not supported.", this); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java index 306276a8339..e1ae316fe54 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java @@ -72,8 +72,9 @@ public CreateNewDatasetCommand(Dataset theDataset, DataverseRequest aRequest, Te @Override protected void additionalParameterTests(CommandContext ctxt) throws CommandException { if ( nonEmpty(getDataset().getIdentifier()) ) { - PidProvider idServiceBean = PidProvider.getBean(getDataset().getProtocol(), ctxt); - if ( !idServiceBean.isGlobalIdUnique(getDataset().getGlobalId()) ) { + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(getDataset()); + + if ( !pidProvider.isGlobalIdUnique(getDataset().getGlobalId()) ) { throw new IllegalCommandException(String.format("Dataset with identifier '%s', protocol '%s' and authority '%s' already exists", getDataset().getIdentifier(), getDataset().getProtocol(), getDataset().getAuthority()), this); @@ -88,11 +89,11 @@ protected DatasetVersion getVersionToPersist( Dataset theDataset ) { @Override protected void handlePid(Dataset theDataset, CommandContext ctxt) throws CommandException { - PidProvider idServiceBean = PidProvider.getBean(ctxt); - if(!idServiceBean.canManagePID()) { - throw new IllegalCommandException("PID Provider " + idServiceBean.getProviderInformation().get(0) + " is not configured.", this); + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(theDataset); + if(!pidProvider.canManagePID()) { + throw new IllegalCommandException("PID Provider " + pidProvider.getProviderInformation().get(0) + " is not configured.", this); } - if ( !idServiceBean.registerWhenPublished() ) { + if ( !pidProvider.registerWhenPublished() ) { // pre-register a persistent id registerExternalIdentifier(theDataset, ctxt, true); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java index 997a2d365b1..f502098e96a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java @@ -1,6 +1,7 @@ package edu.harvard.iq.dataverse.engine.command.impl; import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; @@ -12,6 +13,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.util.FileUtil; import edu.harvard.iq.dataverse.util.StringUtil; import java.io.IOException; @@ -202,15 +204,18 @@ public FileVisitResult postVisitDirectory(final Path dir, final IOException e) */ } } - PidProvider idServiceBean = PidProvider.getBean(ctxt); - try { - if (idServiceBean.alreadyRegistered(doomed)) { - idServiceBean.deleteIdentifier(doomed); + GlobalId pid = doomed.getGlobalId(); + if (pid != null) { + PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderName()); + + try { + if (pidProvider.alreadyRegistered(doomed)) { + pidProvider.deleteIdentifier(doomed); + } + } catch (Exception e) { + logger.log(Level.WARNING, "Identifier deletion was not successfull:", e.getMessage()); } - } catch (Exception e) { - logger.log(Level.WARNING, "Identifier deletion was not successfull:", e.getMessage()); } - DataFile doomedAndMerged = ctxt.em().merge(doomed); ctxt.em().remove(doomedAndMerged); /** diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java index 92c42b1ce49..b1d7c4a5437 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java @@ -11,7 +11,6 @@ import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import org.apache.commons.httpclient.HttpException; @@ -42,11 +41,10 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { this, Collections.singleton(Permission.EditDataset), dataset); } - String nonNullDefaultIfKeyNotFound = ""; - String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(dataset); + try { - idServiceBean.deleteIdentifier(dataset); + pidProvider.deleteIdentifier(dataset); // Success! Clear the create time, etc. dataset.setGlobalIdCreateTime(null); dataset.setIdentifierRegistered(false); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java index 1966743340c..f608b636cc6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java @@ -3,6 +3,7 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.Dataverse; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.DataverseRole; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.RoleAssignment; @@ -16,6 +17,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.search.IndexResponse; import java.util.ArrayList; import java.util.Collections; @@ -100,18 +102,21 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { } if (!doomed.isHarvested()) { - PidProvider idServiceBean = PidProvider.getBean(ctxt); - try { - if (idServiceBean.alreadyRegistered(doomed)) { - idServiceBean.deleteIdentifier(doomed); - for (DataFile df : doomed.getFiles()) { - idServiceBean.deleteIdentifier(df); + GlobalId pid = doomed.getGlobalId(); + if (pid != null) { + PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderName()); + try { + if (pidProvider.alreadyRegistered(doomed)) { + pidProvider.deleteIdentifier(doomed); + for (DataFile df : doomed.getFiles()) { + pidProvider.deleteIdentifier(df); + } } + } catch (Exception e) { + logger.log(Level.WARNING, "Identifier deletion was not successful:", e.getMessage()); } - } catch (Exception e) { - logger.log(Level.WARNING, "Identifier deletion was not successful:", e.getMessage()); } - } + } toReIndex = managedDoomed.getOwner(); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java index 0566c9e3fb6..78a546d7599 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java @@ -21,6 +21,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.export.ExportService; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; @@ -387,9 +388,9 @@ private void validateDataFiles(Dataset dataset, CommandContext ctxt) throws Comm private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) throws CommandException { String protocol = getDataset().getProtocol(); String authority = getDataset().getAuthority(); - PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); + PidProvider pidProvider = PidUtil.getPidProvider(getDataset().getGlobalId().getProviderName()); - if (idServiceBean != null) { + if (pidProvider != null) { try { String currentGlobalIdProtocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, ""); @@ -405,6 +406,7 @@ private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) t // an authority that's different from what's currently configured. // Additionaly in 4.9.3 we have added a system variable to disable // registering file PIDs on the installation level. + //ToDo - update to handle multiple PidProviders if (((currentGlobalIdProtocol.equals(protocol) && currentGlobalAuthority.equals(authority)) || dataFilePIDFormat.equals("INDEPENDENT")) && isFilePIDsEnabled @@ -414,17 +416,17 @@ private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) t for (DataFile df : dataset.getFiles()) { logger.log(Level.FINE, "registering global id for file {0}", df.getId()); //A false return value indicates a failure in calling the service - if (!idServiceBean.publicizeIdentifier(df)) { + if (!pidProvider.publicizeIdentifier(df)) { throw new Exception(); } df.setGlobalIdCreateTime(getTimestamp()); df.setIdentifierRegistered(true); } } - if (!idServiceBean.publicizeIdentifier(dataset)) { + if (!pidProvider.publicizeIdentifier(dataset)) { throw new Exception(); } - dataset.setGlobalIdCreateTime(new Date()); // TODO these two methods should be in the responsibility of the idServiceBean. + dataset.setGlobalIdCreateTime(new Date()); // TODO these two methods should be in the responsibility of the pidProvider. dataset.setIdentifierRegistered(true); } catch (Throwable e) { logger.warning("Failed to register the identifier "+dataset.getGlobalId().asString()+", or to register a file in the dataset; notifying the user(s), unlocking the dataset"); @@ -433,7 +435,7 @@ private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) t notifyUsersDatasetPublishStatus(ctxt, dataset, UserNotification.Type.PUBLISHFAILED_PIDREG); ctxt.datasets().removeDatasetLocks(dataset, DatasetLock.Reason.finalizePublication); - throw new CommandException(BundleUtil.getStringFromBundle("dataset.publish.error", idServiceBean.getProviderInformation()), this); + throw new CommandException(BundleUtil.getStringFromBundle("dataset.publish.error", pidProvider.getProviderInformation()), this); } } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java index 55d7f44ccb9..83b78f68f26 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java @@ -80,9 +80,9 @@ protected void additionalParameterTests(CommandContext ctxt) throws CommandExcep * Dataverse) but aren't findable to be used. That could be the case if, for * example, someone was importing a draft dataset from elsewhere. */ - PidProvider globalIdServiceBean = PidProvider.getBean(ds.getProtocol(), ctxt); - if (globalIdServiceBean != null) { - if (globalIdServiceBean.alreadyRegistered(ds.getGlobalId(), true)) { + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(ds); + if (pidProvider != null) { + if (pidProvider.alreadyRegistered(ds.getGlobalId(), true)) { return; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java index 27ca856580b..c481f13d465 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java @@ -52,17 +52,17 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { String nonNullDefaultIfKeyNotFound = ""; String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); String authority = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); - // Get the idServiceBean that is configured to mint new IDs - PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); + // Get the pidProvider that is configured to mint new IDs + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(target); try { //Test to see if identifier already present //if so, leave. if (target.getIdentifier() == null || target.getIdentifier().isEmpty()) { if (target.isInstanceofDataset()) { - target.setIdentifier(idServiceBean.generateDatasetIdentifier((Dataset) target)); + target.setIdentifier(pidProvider.generateDatasetIdentifier((Dataset) target)); } else { - target.setIdentifier(idServiceBean.generateDataFileIdentifier((DataFile) target)); + target.setIdentifier(pidProvider.generateDataFileIdentifier((DataFile) target)); } if (target.getProtocol() == null) { target.setProtocol(protocol); @@ -71,12 +71,12 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { target.setAuthority(authority); } } - if (idServiceBean.alreadyRegistered(target)) { + if (pidProvider.alreadyRegistered(target)) { return; } - String doiRetString = idServiceBean.createIdentifier(target); + String doiRetString = pidProvider.createIdentifier(target); if (doiRetString != null && doiRetString.contains(target.getIdentifier())) { - if (!idServiceBean.registerWhenPublished()) { + if (!pidProvider.registerWhenPublished()) { // Should register ID before publicize() is called // For example, DOIEZIdProvider tries to recreate the id if the identifier isn't registered before // publicizeIdentifier is called @@ -84,9 +84,9 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { target.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); } if (target.isReleased()) { - idServiceBean.publicizeIdentifier(target); + pidProvider.publicizeIdentifier(target); } - if (idServiceBean.registerWhenPublished() && target.isReleased()) { + if (pidProvider.registerWhenPublished() && target.isReleased()) { target.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); target.setIdentifierRegistered(true); } @@ -96,7 +96,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { Dataset dataset = (Dataset) target; for (DataFile df : dataset.getFiles()) { if (df.getIdentifier() == null || df.getIdentifier().isEmpty()) { - df.setIdentifier(idServiceBean.generateDataFileIdentifier(df)); + df.setIdentifier(pidProvider.generateDataFileIdentifier(df)); if (df.getProtocol() == null || df.getProtocol().isEmpty()) { df.setProtocol(protocol); } @@ -104,9 +104,9 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { df.setAuthority(authority); } } - doiRetString = idServiceBean.createIdentifier(df); + doiRetString = pidProvider.createIdentifier(df); if (doiRetString != null && doiRetString.contains(df.getIdentifier())) { - if (!idServiceBean.registerWhenPublished()) { + if (!pidProvider.registerWhenPublished()) { // Should register ID before publicize() is called // For example, DOIEZIdProvider tries to recreate the id if the identifier isn't registered before // publicizeIdentifier is called @@ -114,9 +114,9 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { df.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); } if (df.isReleased()) { - idServiceBean.publicizeIdentifier(df); + pidProvider.publicizeIdentifier(df); } - if (idServiceBean.registerWhenPublished() && df.isReleased()) { + if (pidProvider.registerWhenPublished() && df.isReleased()) { df.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); df.setIdentifierRegistered(true); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java index a956cce45d4..65324860894 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import java.util.Arrays; @@ -41,11 +42,10 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { this, Collections.singleton(Permission.EditDataset), dataset); } - String nonNullDefaultIfKeyNotFound = ""; - String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - PidProvider idServiceBean = PidProvider.getBean(protocol, ctxt); + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(dataset); + try { - String returnString = idServiceBean.createIdentifier(dataset); + String returnString = pidProvider.createIdentifier(dataset); logger.fine(returnString); // No errors caught, so mark PID as reserved. dataset.setGlobalIdCreateTime(new Date()); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java index 8c272d11f15..ce82ea17a29 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import java.sql.Timestamp; import java.util.Collections; @@ -37,15 +38,15 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { throw new PermissionException("Update Target URL can only be called by superusers.", this, Collections.singleton(Permission.EditDataset), target); } - PidProvider idServiceBean = PidProvider.getBean(target.getProtocol(), ctxt); + PidProvider pidProvider = PidUtil.getPidProvider(target.getGlobalId().getProviderName()); try { - String doiRetString = idServiceBean.modifyIdentifierTargetURL(target); + String doiRetString = pidProvider.modifyIdentifierTargetURL(target); if (doiRetString != null && doiRetString.contains(target.getIdentifier())) { target.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); ctxt.em().merge(target); ctxt.em().flush(); for (DataFile df : target.getFiles()) { - doiRetString = idServiceBean.modifyIdentifierTargetURL(df); + doiRetString = pidProvider.modifyIdentifierTargetURL(df); if (doiRetString != null && doiRetString.contains(df.getIdentifier())) { df.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); ctxt.em().merge(df); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java index 78c9a6e4a83..529aa37a98d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java @@ -46,9 +46,10 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { //the single dataset update api checks for drafts before calling the command return; } - PidProvider idServiceBean = PidProvider.getBean(target.getProtocol(), ctxt); + PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(target); + try { - Boolean doiRetString = idServiceBean.publicizeIdentifier(target); + Boolean doiRetString = pidProvider.publicizeIdentifier(target); if (doiRetString) { target.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); ctxt.em().merge(target); @@ -70,7 +71,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { currentGlobalIdProtocol.equals(protocol) || // right protocol to create dependent DOIs, or dataFilePIDFormat.equals("INDEPENDENT"))// or independent. TODO(pm) - check authority too ) { - doiRetString = idServiceBean.publicizeIdentifier(df); + doiRetString = pidProvider.publicizeIdentifier(df); if (doiRetString) { df.setGlobalIdCreateTime(new Timestamp(new Date().getTime())); ctxt.em().merge(df); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index f34a9f20fb3..2389a166dc3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -74,26 +74,6 @@ public interface PidProvider { String getShoulder(); String getIdentifierGenerationStyle(); - - //ToDo - now need to get the correct provider based on the protocol, authority, and shoulder (for new pids)/indentifier (for existing pids) - static PidProvider getBean(String protocol, CommandContext ctxt) { - final Function protocolHandler = BeanDispatcher.DISPATCHER.get(protocol); - if ( protocolHandler != null ) { - PidProvider theBean = protocolHandler.apply(ctxt); - if(theBean != null) { - logger.fine("getBean returns " + theBean.getProviderInformation().get(0) + " for protocol " + protocol); - } - return theBean; - } else { - logger.log(Level.SEVERE, "Unknown protocol: {0}", protocol); - return null; - } - } - - static PidProvider getBean(CommandContext ctxt) { - return getBean(ctxt.settings().getValueForKey(Key.Protocol, ""), ctxt); - } - public static Optional parse(String identifierString) { try { return Optional.of(PidUtil.parseAsGlobalID(identifierString)); @@ -198,41 +178,4 @@ static boolean checkDOIAuthority(String doiAuthority){ Set getExcludedSet(); -} - - -/* - * ToDo - replace this with a mechanism like BrandingUtilHelper that would read - * the config and create PidProviders, one per set of config values and serve - * those as needed. The help has to be a bean to autostart and to hand the - * required service beans to the PidProviders. That may boil down to just the - * dvObjectService (to check for local identifier conflicts) since it will be - * the helper that has to read settings/get systewmConfig values. - * - */ - -/** - * Static utility class for dispatching implementing beans, based on protocol and providers. - * @author michael - */ -// FWIW: For lists of PIDs not managed by the provider covered by authority/shoulder, we need a way to add them to one provider and exlude them if another registered provider handles their authority/shoulder (probably rare?) -class BeanDispatcher { - static final Map> DISPATCHER = new HashMap<>(); - - static { - DISPATCHER.put("hdl", ctxt->ctxt.handleNet() ); - DISPATCHER.put("doi", ctxt->{ - String doiProvider = ctxt.settings().getValueForKey(Key.DoiProvider, ""); - switch ( doiProvider ) { - case "EZID": return ctxt.doiEZId(); - case "DataCite": return ctxt.doiDataCite(); - case "FAKE": return ctxt.fakePidProvider(); - default: - logger.log(Level.SEVERE, "Unknown doiProvider: {0}", doiProvider); - return null; - } - }); - - DISPATCHER.put(PermaLinkPidProvider.PERMA_PROTOCOL, ctxt->ctxt.permaLinkProvider() ); - } } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 8e4251d10cc..f71700468d7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -29,6 +29,7 @@ import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.pidproviders.PidProvider; @@ -49,15 +50,12 @@ public class PidProviderFactoryBean { @Inject DataverseServiceBean dataverseService; @EJB - protected - SettingsServiceBean settingsService; + protected SettingsServiceBean settingsService; @Inject - protected - DvObjectServiceBean dvObjectService; + protected DvObjectServiceBean dvObjectService; @Inject SystemConfig systemConfig; - private ServiceLoader loader; private Map pidProviderFactoryMap = new HashMap<>(); @@ -125,21 +123,45 @@ private void loadProviders() { PidUtil.addToProviderList(provider); } } - PidUtil.addAllToUnmanagedProviderList(Arrays.asList(new UnmanagedDOIProvider(), new UnmanagedHandlePidProvider(), new UnmanagedPermaLinkPidProvider())); + PidUtil.addAllToUnmanagedProviderList(Arrays.asList(new UnmanagedDOIProvider(), + new UnmanagedHandlePidProvider(), new UnmanagedPermaLinkPidProvider())); } - public String getProducer() { + String getProducer() { return dataverseService.getRootDataverseName(); } - public boolean isGlobalIdLocallyUnique(GlobalId globalId) { + boolean isGlobalIdLocallyUnique(GlobalId globalId) { return dvObjectService.isGlobalIdLocallyUnique(globalId); } - public String generateNewIdentifierByStoredProcedure() { + String generateNewIdentifierByStoredProcedure() { return dvObjectService.generateNewIdentifierByStoredProcedure(); } + + /** + * A method to get the PidProvider for a given DvObject - intended for use when it is not known whether the object has a PID yet or not. + * If it does, the PidUtil method can be called directly to get the PidProvider. + * @param dvObject + * @return - a PidProvider for the object (may be one of the Unmanaged providers) + */ - + public PidProvider getPidProvider(DvObject dvObject) { + GlobalId pid = dvObject.getGlobalId(); + if (pid != null) { + return PidUtil.getPidProvider(pid.getProviderName()); + } else { + // ToDo - get parent settings rather than global + String nonNullDefaultIfKeyNotFound = ""; + String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol, + nonNullDefaultIfKeyNotFound); + String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority, + nonNullDefaultIfKeyNotFound); + String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder, + nonNullDefaultIfKeyNotFound); + + return PidUtil.getPidProvider(protocol, authority, shoulder); + } + } } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 41a35c1fe7c..c846840cda3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -1,5 +1,6 @@ package edu.harvard.iq.dataverse.pidproviders; +import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.util.BundleUtil; import java.io.IOException; @@ -186,9 +187,9 @@ public static GlobalId parseAsGlobalID(String protocol, String authority, String * This method should be deprecated/removed when further refactoring to support * multiple PID providers is done. At that point, when the providers aren't * beans, this code can be moved into other classes that go in the providerMap. - * If this method is not kept in sync with the DOIProvider and - * HandlePidProvider implementations, the tests using it won't be valid tests - * of the production code. + * If this method is not kept in sync with the DOIProvider and HandlePidProvider + * implementations, the tests using it won't be valid tests of the production + * code. */ private static GlobalId parseUnmanagedDoiOrHandle(String protocol, String authority, String identifier) { @@ -210,4 +211,46 @@ private static GlobalId parseUnmanagedDoiOrHandle(String protocol, String author } return new GlobalId(protocol, authority, identifier, "/", urlPrefix, null); } + + /** + * Get a PidProvider by name. GlobalIds have a getProviderName() method so this + * method is often used as + * getPidProvider(dvObject.getGlobalId().getProviderName(); (which will fail if + * the GlobalId is null - use PidProviderFactoryBean.getPidProvider(DvObject) if + * you aren't sure. + * + */ + + public static PidProvider getPidProvider(String name) { + for (PidProvider pidProvider : providerMap.values()) { + if (name.equals(pidProvider.getName())) { + return pidProvider; + } + } + for (PidProvider pidProvider : unmanagedProviderMap.values()) { + if (name.equals(pidProvider.getName())) { + return pidProvider; + } + } + return null; + } + + /** + * Get a PidProvider by protocol/authority/shoulder. + */ + public static PidProvider getPidProvider(String protocol, String authority, String shoulder) { + for (PidProvider pidProvider : providerMap.values()) { + if (protocol.equals(pidProvider.getProtocol()) && authority.equals(pidProvider.getAuthority()) + && shoulder.equals(pidProvider.getShoulder())) { + return pidProvider; + } + } + for (PidProvider pidProvider : unmanagedProviderMap.values()) { + if (protocol.equals(pidProvider.getProtocol())) { + return pidProvider; + } + } + return null; + } + } From ee83e1cd5141ff4a8365a2b38f96e4caa13d5b79 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 15:03:05 -0500 Subject: [PATCH 015/113] update tests, comment out ones that are TBD --- .../dataverse/engine/TestCommandContext.java | 28 +--------- .../PersistentIdentifierProviderTest.java} | 52 +++++-------------- .../dataverse/pidproviders/PidUtilTest.java | 28 ++++++---- 3 files changed, 31 insertions(+), 77 deletions(-) rename src/test/java/edu/harvard/iq/dataverse/{PersistentIdentifierServiceBeanTest.java => pidproviders/PersistentIdentifierProviderTest.java} (71%) diff --git a/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java b/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java index 2b509254f0e..255125189ae 100644 --- a/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java +++ b/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java @@ -11,11 +11,7 @@ import edu.harvard.iq.dataverse.engine.command.Command; import edu.harvard.iq.dataverse.engine.command.CommandContext; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -125,27 +121,7 @@ public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels() { } @Override - public DOIEZIdProvider doiEZId() { - return null; - } - - @Override - public DataCiteDOIProvider doiDataCite() { - return null; - } - - @Override - public FakeDOIProvider fakePidProvider() { - return null; - } - - @Override - public HandlePidProvider handleNet() { - return null; - } - - @Override - public PermaLinkPidProvider permaLinkProvider() { + public PidProviderFactoryBean pidProviderFactory() { return null; } diff --git a/src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PersistentIdentifierProviderTest.java similarity index 71% rename from src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java rename to src/test/java/edu/harvard/iq/dataverse/pidproviders/PersistentIdentifierProviderTest.java index da25e65fc35..a3f23940cc4 100644 --- a/src/test/java/edu/harvard/iq/dataverse/PersistentIdentifierServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PersistentIdentifierProviderTest.java @@ -3,16 +3,12 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse; +package edu.harvard.iq.dataverse.pidproviders; import edu.harvard.iq.dataverse.engine.TestCommandContext; import edu.harvard.iq.dataverse.engine.command.CommandContext; -import edu.harvard.iq.dataverse.pidproviders.DOIEZIdProvider; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,19 +27,13 @@ * @author michael */ @ExtendWith(MockitoExtension.class) -public class PersistentIdentifierServiceBeanTest { +public class PersistentIdentifierProviderTest { @Mock private SettingsServiceBean settingsServiceBean; @InjectMocks - DOIEZIdProvider ezidServiceBean = new DOIEZIdProvider(); - @InjectMocks - DataCiteDOIProvider dataCiteServiceBean = new DataCiteDOIProvider(); - @InjectMocks - FakeDOIProvider fakePidProviderServiceBean = new FakeDOIProvider(); - HandlePidProvider hdlServiceBean = new HandlePidProvider(); - PermaLinkPidProvider permaLinkServiceBean = new PermaLinkPidProvider(); + PidProviderFactoryBean pidProviderFactoryBean = new PidProviderFactoryBean(); CommandContext ctxt; @@ -52,36 +42,16 @@ public void setup() { MockitoAnnotations.initMocks(this); ctxt = new TestCommandContext(){ @Override - public HandlePidProvider handleNet() { - return hdlServiceBean; - } - - @Override - public DataCiteDOIProvider doiDataCite() { - return dataCiteServiceBean; - } - - @Override - public DOIEZIdProvider doiEZId() { - return ezidServiceBean; + public PidProviderFactoryBean pidProviderFactory() { + return pidProviderFactoryBean; } - - @Override - public FakeDOIProvider fakePidProvider() { - return fakePidProviderServiceBean; - } - - @Override - public PermaLinkPidProvider permaLinkProvider() { - return permaLinkServiceBean; - } - }; } /** * Test of getBean method, of class PersistentIdentifierServiceBean. */ + /* @Test public void testGetBean_String_CommandContext_OK() { ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "EZID"); @@ -108,7 +78,8 @@ public void testGetBean_String_CommandContext_OK() { assertEquals(permaLinkServiceBean, PidProvider.getBean("perma", ctxt)); } - + */ + /* @Test public void testGetBean_String_CommandContext_BAD() { ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "non-existent-provider"); @@ -117,10 +88,11 @@ public void testGetBean_String_CommandContext_BAD() { assertNull(PidProvider.getBean("non-existent-protocol", ctxt)); } - +*/ /** * Test of getBean method, of class PersistentIdentifierServiceBean. */ + /* @Test public void testGetBean_CommandContext() { ctxt.settings().setValueForKey( SettingsServiceBean.Key.Protocol, "doi"); @@ -139,5 +111,5 @@ public void testGetBean_CommandContext() { PidProvider.getBean("perma", ctxt)); } - +*/ } diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index ccf0de93f25..34399a7263a 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -1,8 +1,12 @@ package edu.harvard.iq.dataverse.pidproviders; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.json.JsonUtil; +import edu.harvard.iq.dataverse.util.testing.JvmSetting; +import edu.harvard.iq.dataverse.util.testing.LocalJvmSettings; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -26,19 +30,17 @@ * Useful for testing but requires DataCite credentials, etc. */ @ExtendWith(MockitoExtension.class) +@LocalJvmSettings public class PidUtilTest { + @Mock private SettingsServiceBean settingsServiceBean; - @InjectMocks - private PermaLinkPidProvider p = new PermaLinkPidProvider(); - @BeforeEach public void initMocks() { MockitoAnnotations.initMocks(this); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol)).thenReturn("perma"); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("DANSLINK"); - p.reInit(); +// Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol)).thenReturn("perma"); +// Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("DANSLINK"); } @Disabled @@ -58,13 +60,17 @@ public void testGetDoi() throws IOException { } @Test + @JvmSetting(key = JvmSettings.PID_PROVIDER_NAME, value = "perma1", varArgs = "api-bearer-auth") + @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") + @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma1") + @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma1") + @JvmSetting(key = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") public void testGetPermaLink() throws IOException { - List list = new ArrayList(); - - list.add(p); - PidUtil.addAllToProviderList(list); - GlobalId pid = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE5A-XN55", "", p.getUrlPrefix(), PermaLinkPidProvider.PERMA_PROVIDER_NAME); + PidProvider p = new PermaLinkProviderFactory().createPidProvider("perma1"); + PidUtil.clearPidProviders(); + PidUtil.addToProviderList(p); + GlobalId pid = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE5A-XN55", "", p.getUrlPrefix(), "perma1"); System.out.println(pid.asString()); System.out.println(pid.asURL()); From d8bf8a8998b813e9649b5f121e544971f9d9702c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 15:03:44 -0500 Subject: [PATCH 016/113] add clear method for testing --- .../edu/harvard/iq/dataverse/pidproviders/PidUtil.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index c846840cda3..6a0a9db6105 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -1,6 +1,5 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.util.BundleUtil; import java.io.IOException; @@ -253,4 +252,12 @@ public static PidProvider getPidProvider(String protocol, String authority, Stri return null; } + /** + * Method to clear all managed/unmanaged PidProviders. Only for testing as these + * lists are only loaded once by the @Stateless PidProviderFactoryBean in Dataverse. + */ + public static void clearPidProviders() { + providerMap.clear(); + unmanagedProviderMap.clear(); + } } From 80d8416457c94004e8d498cdcb92e415f9240aad Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 15:05:02 -0500 Subject: [PATCH 017/113] bugs - remove dup authority, fix name, add auth/sep/shoulder tests --- .../pidproviders/PermaLinkPidProvider.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index a7c5c5b559c..24171a4a908 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -37,8 +37,6 @@ public class PermaLinkPidProvider extends AbstractPidProvider { .orElse(SystemConfig.getDataverseSiteUrlStatic()); - - String authority = null; private String separator = ""; private String baseUrl; @@ -71,7 +69,7 @@ public boolean registerWhenPublished() { @Override public List getProviderInformation() { - return List.of(PERMA_PROVIDER_NAME, getBaseUrl()); + return List.of(getName(), getBaseUrl()); } @Override @@ -113,6 +111,7 @@ public boolean publicizeIdentifier(DvObject dvObject) { @Override public GlobalId parsePersistentId(String pidString) { // ToDo - handle local PID resolver for dataset/file + logger.info("Parsing in Perma: " + pidString); if (pidString.startsWith(getUrlPrefix())) { pidString = pidString.replace(getUrlPrefix(), (PERMA_PROTOCOL + ":")); } @@ -121,21 +120,34 @@ public GlobalId parsePersistentId(String pidString) { @Override public GlobalId parsePersistentId(String protocol, String identifierString) { - logger.fine("Checking Perma: " + identifierString); + logger.info("Checking Perma: " + identifierString); if (!PERMA_PROTOCOL.equals(protocol)) { return null; } String identifier = null; - if (authority != null) { - if (identifierString.startsWith(authority)) { - identifier = identifierString.substring(authority.length()); + if (getAuthority() != null) { + if (identifierString.startsWith(getAuthority())) { + identifier = identifierString.substring(getAuthority().length()); + } else { + //Doesn't match authority + return null; + } + if (identifier.startsWith(separator)) { + identifier = identifier.substring(separator.length()); + } else { + //Doesn't match separator + return null; } } identifier = PidProvider.formatIdentifierString(identifier); if (PidProvider.testforNullTerminator(identifier)) { return null; } - return new GlobalId(PERMA_PROTOCOL, authority, identifier, separator, getUrlPrefix(), PERMA_PROVIDER_NAME); + if(!identifier.startsWith(getShoulder())) { + //Doesn't match shoulder + return null; + } + return new GlobalId(PERMA_PROTOCOL, getAuthority(), identifier, separator, getUrlPrefix(), PERMA_PROVIDER_NAME); } @Override From d2ed46c6331368dc6a2e1e39c17b854b0a6b8486 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 15:09:13 -0500 Subject: [PATCH 018/113] make managed/excluded lists optional --- .../pidproviders/DataCiteProviderFactory.java | 38 ++++++++++--------- .../pidproviders/EZIdProviderFactory.java | 4 +- .../pidproviders/HandleProviderFactory.java | 4 +- .../PermaLinkProviderFactory.java | 4 +- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index bce9bed45ea..b49067edc37 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -7,25 +7,27 @@ class DataCiteProviderFactory implements PidProviderFactory { @Override public PidProvider createPidProvider(String providerName) { - String providerType=JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); - if(!providerType.equals(DataCiteDOIProvider.TYPE)) { - //Being asked to create a non-DataCite provider - return null; - } - String providerAuthority=JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder=JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); - String identifierGenerationStyle=JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE.lookupOptional(providerName).orElse("randomString"); - String datafilePidFormat=JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName).orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); - String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); - - String mdsUrl=JvmSettings.DATACITE_MDS_API_URL.lookup(providerName); - String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerName); - String username = JvmSettings.DATACITE_USERNAME.lookup(providerName); - String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + if (!providerType.equals(DataCiteDOIProvider.TYPE)) { + // Being asked to create a non-DataCite provider + return null; + } + String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); + String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + String identifierGenerationStyle = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE + .lookupOptional(providerName).orElse("randomString"); + String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerName).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); - - return new DataCiteDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); + String mdsUrl = JvmSettings.DATACITE_MDS_API_URL.lookup(providerName); + String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerName); + String username = JvmSettings.DATACITE_USERNAME.lookup(providerName); + String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); + + return new DataCiteDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); } public String getType() { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java index 0f6224afaab..5a949c63b16 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java @@ -18,8 +18,8 @@ public PidProvider createPidProvider(String providerName) { .lookupOptional(providerName).orElse("randomString"); String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); - String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerName).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); String baseUrl = JvmSettings.EZID_API_URL.lookup(providerName); String username = JvmSettings.EZID_USERNAME.lookup(providerName); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java index 8e5a1aef4cb..e81e1452a43 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java @@ -18,8 +18,8 @@ public PidProvider createPidProvider(String providerName) { .lookupOptional(providerName).orElse("randomString"); String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); - String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerName).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); int index = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, providerName); boolean independentHandleService = JvmSettings.HANDLENET_INDEPENDENT_SERVICE diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java index 95852f03232..75570300151 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java @@ -18,8 +18,8 @@ public PidProvider createPidProvider(String providerName) { .lookupOptional(providerName).orElse("randomString"); String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) .orElse(SystemConfig.DataFilePIDFormat.DEPENDENT.toString()); - String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerName); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerName).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); String baseUrl = JvmSettings.PERMALINK_BASE_URL.lookupOptional(providerName) .orElse(SystemConfig.getDataverseSiteUrlStatic()); From fea3976c26355025496b098bc8335d73f4576712 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 16:02:43 -0500 Subject: [PATCH 019/113] fix name in generated pids --- .../iq/dataverse/pidproviders/PermaLinkPidProvider.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 24171a4a908..1ed653f9351 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -29,7 +29,6 @@ public class PermaLinkPidProvider extends AbstractPidProvider { public static final String PERMA_PROTOCOL = "perma"; public static final String TYPE = "perma"; - public static final String PERMA_PROVIDER_NAME = "PERMA"; // ToDo - remove @Deprecated @@ -147,7 +146,7 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { //Doesn't match shoulder return null; } - return new GlobalId(PERMA_PROTOCOL, getAuthority(), identifier, separator, getUrlPrefix(), PERMA_PROVIDER_NAME); + return new GlobalId(PERMA_PROTOCOL, getAuthority(), identifier, separator, getUrlPrefix(), getName()); } @Override From 4c8c4b8cdd589e9b9c231ca9a16c211601e901a7 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 16:03:28 -0500 Subject: [PATCH 020/113] move setup to berforeall, add test of second permaprovider --- .../dataverse/pidproviders/PidUtilTest.java | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 34399a7263a..48e4471209e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -15,6 +15,7 @@ import jakarta.ws.rs.NotFoundException; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; @@ -31,11 +32,33 @@ */ @ExtendWith(MockitoExtension.class) @LocalJvmSettings +@JvmSetting(key = JvmSettings.PID_PROVIDER_NAME, value = "perma1", varArgs = "perma1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma1") +@JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "-", varArgs = "perma1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_NAME, value = "perma2", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "/", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma2") public class PidUtilTest { @Mock private SettingsServiceBean settingsServiceBean; + @BeforeAll + //FWIW @JvmSetting doesn't appear to work with @BeforeAll + public static void setUpClass() throws Exception { + //ToDo - permalinks: use one "" separator and update code to allow prioritizing PidProviders + PidProvider p = new PermaLinkProviderFactory().createPidProvider("perma1"); + PidUtil.clearPidProviders(); + PidUtil.addToProviderList(p); + p = new PermaLinkProviderFactory().createPidProvider("perma2"); + PidUtil.addToProviderList(p); + + } + @BeforeEach public void initMocks() { MockitoAnnotations.initMocks(this); @@ -60,25 +83,28 @@ public void testGetDoi() throws IOException { } @Test - @JvmSetting(key = JvmSettings.PID_PROVIDER_NAME, value = "perma1", varArgs = "api-bearer-auth") - @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") - @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma1") - @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma1") - @JvmSetting(key = JvmSettings.PID_PROVIDER_IDENTIFIER_GENERATION_STYLE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") public void testGetPermaLink() throws IOException { - - PidProvider p = new PermaLinkProviderFactory().createPidProvider("perma1"); - PidUtil.clearPidProviders(); - PidUtil.addToProviderList(p); - GlobalId pid = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE5A-XN55", "", p.getUrlPrefix(), "perma1"); + PidProvider p = PidUtil.getPidProvider("perma1"); + GlobalId pid = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE-5A-XN55", "-", p.getUrlPrefix(), "perma1"); System.out.println(pid.asString()); System.out.println(pid.asURL()); + + GlobalId pid2 = PidUtil.parseAsGlobalID(pid.asString()); assertEquals(pid.asString(), pid2.asString()); + assertEquals("perma1", pid2.getProviderName()); GlobalId pid3 = PidUtil.parseAsGlobalID(pid.asURL()); assertEquals(pid.asString(), pid3.asString()); + assertEquals("perma1", pid3.getProviderName()); + + p = PidUtil.getPidProvider("perma2"); + GlobalId pid5 = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE/5A-XN55", "/", p.getUrlPrefix(), "perma2"); + GlobalId pid6 = PidUtil.parseAsGlobalID(pid5.asString()); + assertEquals("perma2", pid6.getProviderName()); + assertEquals(pid5.asString(), pid6.asString()); + } } From d7804d941321406a49b4af1210c6506208ddf2d5 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 16:21:53 -0500 Subject: [PATCH 021/113] provider name->id --- .../pidproviders/AbstractPidProvider.java | 14 +++++----- .../pidproviders/DataCiteDOIProvider.java | 6 ---- .../pidproviders/DataCiteProviderFactory.java | 26 ++++++++--------- .../pidproviders/EZIdDOIProvider.java | 2 +- .../pidproviders/EZIdProviderFactory.java | 24 ++++++++-------- .../pidproviders/FakeProviderFactory.java | 18 ++++++------ .../pidproviders/HandleProviderFactory.java | 28 +++++++++---------- .../pidproviders/PermaLinkPidProvider.java | 4 +-- .../PermaLinkProviderFactory.java | 22 +++++++-------- .../dataverse/pidproviders/PidProvider.java | 2 +- .../iq/dataverse/pidproviders/PidUtil.java | 6 ++-- .../pidproviders/UnmanagedDOIProvider.java | 8 +++--- .../UnmanagedHandlePidProvider.java | 8 +++--- .../UnmanagedPermaLinkPidProvider.java | 4 +-- 14 files changed, 83 insertions(+), 89 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 3c3005628d0..52cca7b3110 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -43,18 +43,18 @@ public abstract class AbstractPidProvider implements PidProvider { private HashSet excludedSet; - private String name; + private String id; - AbstractPidProvider(String name, String protocol) + AbstractPidProvider(String id, String protocol) { - this.name = name; + this.id = id; this.protocol = protocol; this.managedSet = new HashSet(); this.excludedSet = new HashSet(); } - AbstractPidProvider(String name, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { - this.name = name; + AbstractPidProvider(String id, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + this.id = id; this.protocol = protocol; this.authority = authority; this.shoulder = shoulder; @@ -768,7 +768,7 @@ public Set getExcludedSet() { } @Override - public String getName() { - return name; + public String getId() { + return id; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index d7fcad24496..18150efe0ef 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -271,12 +271,6 @@ public String getProviderType() { return null; } - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - public String getMdsUrl() { return mdsUrl; } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index b49067edc37..e398c435bb5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -6,27 +6,27 @@ class DataCiteProviderFactory implements PidProviderFactory { @Override - public PidProvider createPidProvider(String providerName) { - String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + public PidProvider createPidProvider(String providerId) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); if (!providerType.equals(DataCiteDOIProvider.TYPE)) { // Being asked to create a non-DataCite provider return null; } - String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + 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(providerName).orElse("randomString"); - String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .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(providerName).orElse(""); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - String mdsUrl = JvmSettings.DATACITE_MDS_API_URL.lookup(providerName); - String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerName); - String username = JvmSettings.DATACITE_USERNAME.lookup(providerName); - String password = JvmSettings.DATACITE_PASSWORD.lookup(providerName); + String mdsUrl = JvmSettings.DATACITE_MDS_API_URL.lookup(providerId); + String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerId); + String username = JvmSettings.DATACITE_USERNAME.lookup(providerId); + String password = JvmSettings.DATACITE_PASSWORD.lookup(providerId); - return new DataCiteDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + return new DataCiteDOIProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java index f2761aa7186..192c1420c20 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java @@ -289,7 +289,7 @@ public String getProviderType() { } @Override - public String getName() { + public String getId() { // TODO Auto-generated method stub return null; } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java index 5a949c63b16..d34df149b46 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java @@ -6,26 +6,26 @@ class EZIdProviderFactory implements PidProviderFactory { @Override - public PidProvider createPidProvider(String providerName) { - String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + public PidProvider createPidProvider(String providerId) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); if (!providerType.equals(EZIdDOIProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } - String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + 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(providerName).orElse("randomString"); - String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .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(providerName).orElse(""); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - String baseUrl = JvmSettings.EZID_API_URL.lookup(providerName); - String username = JvmSettings.EZID_USERNAME.lookup(providerName); - String password = JvmSettings.EZID_PASSWORD.lookup(providerName); + String baseUrl = JvmSettings.EZID_API_URL.lookup(providerId); + String username = JvmSettings.EZID_USERNAME.lookup(providerId); + String password = JvmSettings.EZID_PASSWORD.lookup(providerId); - return new EZIdDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + return new EZIdDOIProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, baseUrl, username, password); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java index 65e77c00c8c..abbc4231543 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java @@ -6,22 +6,22 @@ class FakeProviderFactory implements PidProviderFactory { @Override - public PidProvider createPidProvider(String providerName) { - String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + public PidProvider createPidProvider(String providerId) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); if (!providerType.equals(FakeDOIProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } - String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + 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(providerName).orElse("randomString"); - String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .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.lookup(providerName); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerName); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerId); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerId); - return new FakeDOIProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + return new FakeDOIProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java index e81e1452a43..a954fe73cb1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java @@ -6,28 +6,28 @@ class HandleProviderFactory implements PidProviderFactory { @Override - public PidProvider createPidProvider(String providerName) { - String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + public PidProvider createPidProvider(String providerId) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); if (!providerType.equals(HandlePidProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } - String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + 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(providerName).orElse("randomString"); - String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .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(providerName).orElse(""); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - int index = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, providerName); + int index = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, providerId); boolean independentHandleService = JvmSettings.HANDLENET_INDEPENDENT_SERVICE - .lookupOptional(Boolean.class, providerName).orElse(false); - String handleAuthHandle = JvmSettings.HANDLENET_AUTH_HANDLE.lookup(providerName); - String path = JvmSettings.HANDLENET_KEY_PATH.lookup(providerName); - String passphrase = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup(providerName); - return new HandlePidProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + .lookupOptional(Boolean.class, providerId).orElse(false); + String handleAuthHandle = JvmSettings.HANDLENET_AUTH_HANDLE.lookup(providerId); + String path = JvmSettings.HANDLENET_KEY_PATH.lookup(providerId); + String passphrase = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup(providerId); + return new HandlePidProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, index, independentHandleService, handleAuthHandle, path, passphrase); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 1ed653f9351..ae595adb7d1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -68,7 +68,7 @@ public boolean registerWhenPublished() { @Override public List getProviderInformation() { - return List.of(getName(), getBaseUrl()); + return List.of(getId(), getBaseUrl()); } @Override @@ -146,7 +146,7 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { //Doesn't match shoulder return null; } - return new GlobalId(PERMA_PROTOCOL, getAuthority(), identifier, separator, getUrlPrefix(), getName()); + return new GlobalId(PERMA_PROTOCOL, getAuthority(), identifier, separator, getUrlPrefix(), getId()); } @Override diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java index 75570300151..eda80922118 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java @@ -6,27 +6,27 @@ class PermaLinkProviderFactory implements PidProviderFactory { @Override - public PidProvider createPidProvider(String providerName) { - String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerName); + public PidProvider createPidProvider(String providerId) { + String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); if (!providerType.equals(PermaLinkPidProvider.TYPE)) { // Being asked to create a non-EZId provider return null; } - String providerAuthority = JvmSettings.PID_PROVIDER_AUTHORITY.lookup(providerName); - String providerShoulder = JvmSettings.PID_PROVIDER_SHOULDER.lookupOptional(providerName).orElse(""); + 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(providerName).orElse("randomString"); - String datafilePidFormat = JvmSettings.PID_PROVIDER_DATAFILE_PID_FORMAT.lookupOptional(providerName) + .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(providerName).orElse(""); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerName).orElse(""); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - String baseUrl = JvmSettings.PERMALINK_BASE_URL.lookupOptional(providerName) + String baseUrl = JvmSettings.PERMALINK_BASE_URL.lookupOptional(providerId) .orElse(SystemConfig.getDataverseSiteUrlStatic()); ; - String separator = JvmSettings.PERMALINK_SEPARATOR.lookupOptional(providerName).orElse(""); + String separator = JvmSettings.PERMALINK_SEPARATOR.lookupOptional(providerId).orElse(""); - return new PermaLinkPidProvider(providerName, providerAuthority, providerShoulder, identifierGenerationStyle, + return new PermaLinkPidProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, baseUrl, separator); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index 2389a166dc3..3c6343749a2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -69,7 +69,7 @@ public interface PidProvider { String getProtocol(); String getProviderType(); - String getName(); + String getId(); String getAuthority(); String getShoulder(); String getIdentifierGenerationStyle(); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 6a0a9db6105..7bfef31a5b4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -120,7 +120,7 @@ private static String acceptOnlyDoi(GlobalId globalId) { static Map unmanagedProviderMap = new HashMap(); public static void addToProviderList(PidProvider pidProvider) { - providerMap.put(pidProvider.getName(), pidProvider); + providerMap.put(pidProvider.getId(), pidProvider); } public static void addAllToUnmanagedProviderList(List list) { @@ -222,12 +222,12 @@ private static GlobalId parseUnmanagedDoiOrHandle(String protocol, String author public static PidProvider getPidProvider(String name) { for (PidProvider pidProvider : providerMap.values()) { - if (name.equals(pidProvider.getName())) { + if (name.equals(pidProvider.getId())) { return pidProvider; } } for (PidProvider pidProvider : unmanagedProviderMap.values()) { - if (name.equals(pidProvider.getName())) { + if (name.equals(pidProvider.getId())) { return pidProvider; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index f779ed77050..20731d10773 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -16,10 +16,10 @@ public class UnmanagedDOIProvider extends DOIProvider { - private static final String NAME = "UnmanagedDOIProvider"; + private static final String ID = "UnmanagedDOIProvider"; public UnmanagedDOIProvider() { - super(NAME); + super(ID); } @Override @@ -73,8 +73,8 @@ public String getProviderType() { } @Override - public String getName() { - return NAME; + public String getId() { + return ID; } // PID recognition diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java index 7ed59022959..83c4c8941bd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java @@ -19,10 +19,10 @@ public class UnmanagedHandlePidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedHandlePidProvider.class.getCanonicalName()); - private static final String NAME = "UnmanagedHandleProvider"; + private static final String ID = "UnmanagedHandleProvider"; public UnmanagedHandlePidProvider() { - super(NAME, HandlePidProvider.HDL_PROTOCOL); + super(ID, HandlePidProvider.HDL_PROTOCOL); logger.log(Level.FINE, "Constructor"); } @@ -111,7 +111,7 @@ public String getProviderType() { } @Override - public String getName() { - return NAME; + public String getId() { + return ID; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java index 5250cd959f9..90a09f88b03 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java @@ -18,10 +18,10 @@ public class UnmanagedPermaLinkPidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedPermaLinkPidProvider.class.getCanonicalName()); - private static final String NAME = "UnmanagedPermaLinkProvider"; + private static final String ID = "UnmanagedPermaLinkProvider"; public UnmanagedPermaLinkPidProvider() { - super(NAME, PermaLinkPidProvider.PERMA_PROTOCOL); + super(ID, PermaLinkPidProvider.PERMA_PROTOCOL); logger.log(Level.FINE, "Constructor"); } From 7ffb1c346fee6bc25d0c5ef6d0bb774971e1db7e Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 16:34:53 -0500 Subject: [PATCH 022/113] adding label, more name->id --- .../dataverse/pidproviders/AbstractPidProvider.java | 12 ++++++++++-- .../iq/dataverse/pidproviders/DOIProvider.java | 8 ++++---- .../dataverse/pidproviders/DataCiteDOIProvider.java | 4 ++-- .../pidproviders/DataCiteProviderFactory.java | 3 ++- .../iq/dataverse/pidproviders/EZIdDOIProvider.java | 4 ++-- .../dataverse/pidproviders/EZIdProviderFactory.java | 3 ++- .../iq/dataverse/pidproviders/FakeDOIProvider.java | 4 ++-- .../dataverse/pidproviders/FakeProviderFactory.java | 3 ++- .../iq/dataverse/pidproviders/HandlePidProvider.java | 4 ++-- .../pidproviders/HandleProviderFactory.java | 3 ++- .../dataverse/pidproviders/PermaLinkPidProvider.java | 4 ++-- .../pidproviders/PermaLinkProviderFactory.java | 3 ++- .../iq/dataverse/pidproviders/PidProvider.java | 1 + .../dataverse/pidproviders/UnmanagedDOIProvider.java | 3 ++- .../pidproviders/UnmanagedHandlePidProvider.java | 3 ++- .../pidproviders/UnmanagedPermaLinkPidProvider.java | 3 ++- .../harvard/iq/dataverse/settings/JvmSettings.java | 2 +- .../iq/dataverse/pidproviders/PidUtilTest.java | 4 ++-- 18 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 52cca7b3110..f7ab4cbee29 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -44,17 +44,20 @@ public abstract class AbstractPidProvider implements PidProvider { private HashSet excludedSet; private String id; + private String label; - AbstractPidProvider(String id, String protocol) + AbstractPidProvider(String id, String label, String protocol) { this.id = id; + this.label = label; this.protocol = protocol; this.managedSet = new HashSet(); this.excludedSet = new HashSet(); } - AbstractPidProvider(String id, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + AbstractPidProvider(String id, String label, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { this.id = id; + this.label = label; this.protocol = protocol; this.authority = authority; this.shoulder = shoulder; @@ -771,4 +774,9 @@ public Set getExcludedSet() { public String getId() { return id; } + + @Override + public String getLabel() { + return label; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java index 50d5510b0ce..ddd8f29f792 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java @@ -11,13 +11,13 @@ public abstract class DOIProvider extends AbstractPidProvider { public static final String DXDOI_RESOLVER_URL = "https://dx.doi.org/"; public static final String HTTP_DXDOI_RESOLVER_URL = "http://dx.doi.org/"; - public DOIProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { - super(name, DOI_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + public DOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + super(id, label, DOI_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } //For Unmanged provider - public DOIProvider(String name) { - super(name, DOI_PROTOCOL); + public DOIProvider(String name, String label) { + super(name, label, DOI_PROTOCOL); } @Override diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index 18150efe0ef..1f89aa15ca8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -43,10 +43,10 @@ public class DataCiteDOIProvider extends DOIProvider { private String username; private String password; - public DataCiteDOIProvider(String name, String providerAuthority, String providerShoulder, String managedList, + public DataCiteDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String managedList, String excludedList, String identifierGenerationStyle, String datafilePidFormat, String mdsUrl, String apiUrl, String username, String password) { - super(name, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, + super(id, label, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.mdsUrl = mdsUrl; this.apiUrl = apiUrl; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index e398c435bb5..1dbf2a87aa2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -12,6 +12,7 @@ public PidProvider createPidProvider(String providerId) { // Being asked to create a non-DataCite 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 @@ -26,7 +27,7 @@ public PidProvider createPidProvider(String providerId) { String username = JvmSettings.DATACITE_USERNAME.lookup(providerId); String password = JvmSettings.DATACITE_PASSWORD.lookup(providerId); - return new DataCiteDOIProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, + return new DataCiteDOIProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, mdsUrl, apiUrl, username, password); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java index 192c1420c20..c161c4bf9d8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java @@ -30,9 +30,9 @@ public class EZIdDOIProvider extends DOIProvider { private String baseUrl; - public EZIdDOIProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, + public EZIdDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, String baseUrl, String username, String password) { - super(name, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + super(id, label, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); // Creating the service doesn't do any harm, just initializing some object data here. // Makes sure we don't run into NPEs from the other methods, but will obviously fail if the // login below does not work. diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java index d34df149b46..d8f3614cd8d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java @@ -12,6 +12,7 @@ public PidProvider createPidProvider(String providerId) { // Being asked to create a non-EZId 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 @@ -25,7 +26,7 @@ public PidProvider createPidProvider(String providerId) { String username = JvmSettings.EZID_USERNAME.lookup(providerId); String password = JvmSettings.EZID_PASSWORD.lookup(providerId); - return new EZIdDOIProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + return new EZIdDOIProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, baseUrl, username, password); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java index 65dbcff0a47..b900897b6ef 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java @@ -11,9 +11,9 @@ public class FakeDOIProvider extends DOIProvider { static final String TYPE = "FAKE"; - public FakeDOIProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, + public FakeDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { - super(name, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + super(id, label, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } //Only need to check locally diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java index abbc4231543..74a865f7e1b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java @@ -12,6 +12,7 @@ public PidProvider createPidProvider(String providerId) { // Being asked to create a non-EZId 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 @@ -21,7 +22,7 @@ public PidProvider createPidProvider(String providerId) { String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookup(providerId); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerId); - return new FakeDOIProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, + return new FakeDOIProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index 1070583c43f..fa06d0214a4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -75,9 +75,9 @@ public class HandlePidProvider extends AbstractPidProvider { private String keyPath; private String keyPassphrase; - HandlePidProvider(String name, String authority, String shoulder, String identifierGenerationStyle, + HandlePidProvider(String id, String label, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, int index, boolean isIndependentService, String authHandle, String path, String passphrase) { - super(name, HDL_PROTOCOL, authority, shoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); + super(id, label, HDL_PROTOCOL, authority, shoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.handlenetIndex = index; this.isIndependentHandleService = isIndependentService; this.authHandle = authHandle; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java index a954fe73cb1..7108c2c631a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java @@ -12,6 +12,7 @@ public PidProvider createPidProvider(String providerId) { // Being asked to create a non-EZId 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 @@ -27,7 +28,7 @@ public PidProvider createPidProvider(String providerId) { String handleAuthHandle = JvmSettings.HANDLENET_AUTH_HANDLE.lookup(providerId); String path = JvmSettings.HANDLENET_KEY_PATH.lookup(providerId); String passphrase = JvmSettings.HANDLENET_KEY_PASSPHRASE.lookup(providerId); - return new HandlePidProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, + return new HandlePidProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, index, independentHandleService, handleAuthHandle, path, passphrase); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index ae595adb7d1..92d88085f2c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -40,9 +40,9 @@ public class PermaLinkPidProvider extends AbstractPidProvider { private String baseUrl; - public PermaLinkPidProvider(String name, String providerAuthority, String providerShoulder, String identifierGenerationStyle, + public PermaLinkPidProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, String baseUrl, String separator) { - super(name, PERMA_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, + super(id, label, PERMA_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.baseUrl = baseUrl; this.separator = separator; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java index eda80922118..d04ae50c452 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java @@ -12,6 +12,7 @@ public PidProvider createPidProvider(String providerId) { // Being asked to create a non-EZId 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 @@ -26,7 +27,7 @@ public PidProvider createPidProvider(String providerId) { ; String separator = JvmSettings.PERMALINK_SEPARATOR.lookupOptional(providerId).orElse(""); - return new PermaLinkPidProvider(providerId, providerAuthority, providerShoulder, identifierGenerationStyle, + return new PermaLinkPidProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList, baseUrl, separator); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index 3c6343749a2..fa96f95e059 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -70,6 +70,7 @@ public interface PidProvider { String getProtocol(); String getProviderType(); String getId(); + String getLabel(); String getAuthority(); String getShoulder(); String getIdentifierGenerationStyle(); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index 20731d10773..ec0776312aa 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -19,7 +19,8 @@ public class UnmanagedDOIProvider extends DOIProvider { private static final String ID = "UnmanagedDOIProvider"; public UnmanagedDOIProvider() { - super(ID); + //Also using ID as label + super(ID, ID); } @Override diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java index 83c4c8941bd..5c1179599e3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java @@ -22,7 +22,8 @@ public class UnmanagedHandlePidProvider extends AbstractPidProvider { private static final String ID = "UnmanagedHandleProvider"; public UnmanagedHandlePidProvider() { - super(ID, HandlePidProvider.HDL_PROTOCOL); + // Also using ID as label + super(ID, ID, HandlePidProvider.HDL_PROTOCOL); logger.log(Level.FINE, "Constructor"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java index 90a09f88b03..3b7065acca9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java @@ -21,7 +21,8 @@ public class UnmanagedPermaLinkPidProvider extends AbstractPidProvider { private static final String ID = "UnmanagedPermaLinkProvider"; public UnmanagedPermaLinkPidProvider() { - super(ID, PermaLinkPidProvider.PERMA_PROTOCOL); + // Also using ID as label + super(ID, ID, PermaLinkPidProvider.PERMA_PROTOCOL); logger.log(Level.FINE, "Constructor"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index 4ee194c6fa3..c2db29d2e48 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -95,7 +95,7 @@ public enum JvmSettings { PROVIDERS_DIRECTORY(SCOPE_PID, "provider-implementations-directory"), SCOPE_PID_PROVIDER(SCOPE_PID), PID_PROVIDER_TYPE(SCOPE_PID_PROVIDER, "type"), - PID_PROVIDER_NAME(SCOPE_PID_PROVIDER, "name"), + PID_PROVIDER_LABEL(SCOPE_PID_PROVIDER, "label"), PID_PROVIDER_AUTHORITY(SCOPE_PID_PROVIDER, "authority"), PID_PROVIDER_SHOULDER(SCOPE_PID_PROVIDER, "shoulder"), PID_PROVIDER_IDENTIFIER_GENERATION_STYLE(SCOPE_PID_PROVIDER, "identifier-generation-style"), diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 48e4471209e..a575c1a44d9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -32,12 +32,12 @@ */ @ExtendWith(MockitoExtension.class) @LocalJvmSettings -@JvmSetting(key = JvmSettings.PID_PROVIDER_NAME, value = "perma1", varArgs = "perma1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma1", varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma1") @JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "-", varArgs = "perma1") -@JvmSetting(key = JvmSettings.PID_PROVIDER_NAME, value = "perma2", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma2", varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma2") @JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "/", varArgs = "perma2") From d4cd9373dc9aec2fb7a256a727d2d0796d15db9c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 17:27:05 -0500 Subject: [PATCH 023/113] providerName->providerId --- .../java/edu/harvard/iq/dataverse/DatasetServiceBean.java | 2 +- src/main/java/edu/harvard/iq/dataverse/GlobalId.java | 8 ++++---- .../engine/command/impl/AbstractDatasetCommand.java | 2 +- .../engine/command/impl/DeleteDataFileCommand.java | 2 +- .../engine/command/impl/DestroyDatasetCommand.java | 2 +- .../command/impl/FinalizeDatasetPublicationCommand.java | 2 +- .../command/impl/UpdateDatasetTargetURLCommand.java | 2 +- .../iq/dataverse/pidproviders/PidProviderFactory.java | 2 +- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java index 35a4c04e6cd..ac6a46a300a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java @@ -958,7 +958,7 @@ the changes from file ingest (which may be happening in parallel, also @Asynchronous @Deprecated public void obtainPersistentIdentifiersForDatafiles(Dataset dataset) { - PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderName()); + PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderId()); //If the Id type is sequential and Dependent then write file identifiers outside the command String datasetIdentifier = dataset.getIdentifier(); diff --git a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java index fea0b1140dc..47495f9ab9f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java +++ b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java @@ -33,7 +33,7 @@ public GlobalId(String protocol, String authority, String identifier, String sep this.separator = separator; } this.urlPrefix = urlPrefix; - this.managingProviderName = providerName; + this.managingProviderId = providerName; } // protocol the identifier system, e.g. "doi" @@ -42,7 +42,7 @@ public GlobalId(String protocol, String authority, String identifier, String sep private String protocol; private String authority; private String identifier; - private String managingProviderName; + private String managingProviderId; private String separator = "/"; private String urlPrefix; @@ -67,8 +67,8 @@ public String getIdentifier() { return identifier; } - public String getProviderName() { - return managingProviderName; + public String getProviderId() { + return managingProviderId; } public String toString() { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java index a06720f2612..e36bf72ec0a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java @@ -153,7 +153,7 @@ protected void validateOrDie(DatasetVersion dsv, Boolean lenient) throws Command */ protected void registerExternalIdentifier(Dataset theDataset, CommandContext ctxt, boolean retry) throws CommandException { if (!theDataset.isIdentifierRegistered()) { - PidProvider pidProvider = PidUtil.getPidProvider(theDataset.getGlobalId().getProviderName()); + PidProvider pidProvider = PidUtil.getPidProvider(theDataset.getGlobalId().getProviderId()); if ( pidProvider != null ) { try { if (pidProvider.alreadyRegistered(theDataset)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java index f502098e96a..0812c52a846 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java @@ -206,7 +206,7 @@ public FileVisitResult postVisitDirectory(final Path dir, final IOException e) } GlobalId pid = doomed.getGlobalId(); if (pid != null) { - PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderName()); + PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderId()); try { if (pidProvider.alreadyRegistered(doomed)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java index f608b636cc6..877f3b81d7e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DestroyDatasetCommand.java @@ -104,7 +104,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { if (!doomed.isHarvested()) { GlobalId pid = doomed.getGlobalId(); if (pid != null) { - PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderName()); + PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderId()); try { if (pidProvider.alreadyRegistered(doomed)) { pidProvider.deleteIdentifier(doomed); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java index 78a546d7599..d6d5a20db27 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java @@ -388,7 +388,7 @@ private void validateDataFiles(Dataset dataset, CommandContext ctxt) throws Comm private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) throws CommandException { String protocol = getDataset().getProtocol(); String authority = getDataset().getAuthority(); - PidProvider pidProvider = PidUtil.getPidProvider(getDataset().getGlobalId().getProviderName()); + PidProvider pidProvider = PidUtil.getPidProvider(getDataset().getGlobalId().getProviderId()); if (pidProvider != null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java index ce82ea17a29..5a0ae7cbf5d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetTargetURLCommand.java @@ -38,7 +38,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { throw new PermissionException("Update Target URL can only be called by superusers.", this, Collections.singleton(Permission.EditDataset), target); } - PidProvider pidProvider = PidUtil.getPidProvider(target.getGlobalId().getProviderName()); + PidProvider pidProvider = PidUtil.getPidProvider(target.getGlobalId().getProviderId()); try { String doiRetString = pidProvider.modifyIdentifierTargetURL(target); if (doiRetString != null && doiRetString.contains(target.getIdentifier())) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java index c7bc1be02c9..570c52a6cdf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java @@ -4,6 +4,6 @@ public interface PidProviderFactory { public String getType(); - public PidProvider createPidProvider(String name); + public PidProvider createPidProvider(String id); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index f71700468d7..3e77acae9ad 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -149,7 +149,7 @@ String generateNewIdentifierByStoredProcedure() { public PidProvider getPidProvider(DvObject dvObject) { GlobalId pid = dvObject.getGlobalId(); if (pid != null) { - return PidUtil.getPidProvider(pid.getProviderName()); + return PidUtil.getPidProvider(pid.getProviderId()); } else { // ToDo - get parent settings rather than global String nonNullDefaultIfKeyNotFound = ""; From 20318e6fade59a4672a54e9baf9621d173252821 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 17:27:47 -0500 Subject: [PATCH 024/113] add factory map, lookups, add factory, perma parsing tests --- .../dataverse/pidproviders/PidUtilTest.java | 103 +++++++++++++----- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index a575c1a44d9..47b3047f28a 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -3,18 +3,23 @@ import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import edu.harvard.iq.dataverse.util.SystemConfig; import edu.harvard.iq.dataverse.util.json.JsonUtil; import edu.harvard.iq.dataverse.util.testing.JvmSetting; import edu.harvard.iq.dataverse.util.testing.LocalJvmSettings; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import jakarta.json.JsonObjectBuilder; import jakarta.ws.rs.NotFoundException; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; @@ -32,16 +37,31 @@ */ @ExtendWith(MockitoExtension.class) @LocalJvmSettings -@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma1", varArgs = "perma1") +//Perma 1 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma 1", varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma1") @JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "-", varArgs = "perma1") -@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma2", varArgs = "perma2") +//Perma 2 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma 2", varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma2") -@JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "/", varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "/", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PERMALINK_BASE_URL, value = "https://example.org/123", varArgs = "perma2") +// Datacite 1 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "dataCite 1", varArgs = "dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5072", varArgs = "dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK2", varArgs = "dc1") +@JvmSetting(key = JvmSettings.DATACITE_MDS_API_URL, value = "https://mds.test.api.org/", varArgs = "dc1") +@JvmSetting(key = JvmSettings.DATACITE_REST_API_URL, value = "https://api.test.datacite.org", varArgs ="dc1") +@JvmSetting(key = JvmSettings.DATACITE_USERNAME, value = "test", varArgs ="dc1") +@JvmSetting(key = JvmSettings.DATACITE_PASSWORD, value = "changeme", varArgs ="dc1") +//List to instantiate +@JvmSetting(key = JvmSettings.PID_PROVIDERS, value = "perma1, perma2, dc1") + public class PidUtilTest { @Mock @@ -50,13 +70,31 @@ public class PidUtilTest { @BeforeAll //FWIW @JvmSetting doesn't appear to work with @BeforeAll public static void setUpClass() throws Exception { - //ToDo - permalinks: use one "" separator and update code to allow prioritizing PidProviders - PidProvider p = new PermaLinkProviderFactory().createPidProvider("perma1"); - PidUtil.clearPidProviders(); - PidUtil.addToProviderList(p); - p = new PermaLinkProviderFactory().createPidProvider("perma2"); - PidUtil.addToProviderList(p); + //This mimics the initial config in the PidProviderFactoryBean.loadProviderFactories method - could potentially be used to mock that bean at some point + Map pidProviderFactoryMap = new HashMap<>(); + pidProviderFactoryMap.put(PermaLinkPidProvider.TYPE, new PermaLinkProviderFactory()); + pidProviderFactoryMap.put(DataCiteDOIProvider.TYPE, new DataCiteProviderFactory()); + pidProviderFactoryMap.put(HandlePidProvider.TYPE, new HandleProviderFactory()); + pidProviderFactoryMap.put(FakeDOIProvider.TYPE, new FakeProviderFactory()); + pidProviderFactoryMap.put(EZIdDOIProvider.TYPE, new EZIdProviderFactory()); + + PidUtil.clearPidProviders(); + + //Read list of providers to add + List providers = Arrays.asList(JvmSettings.PID_PROVIDERS.lookup().split(",\\s")); + //Iterate through the list of providers and add them using the PidProviderFactory of the appropriate type + for (String providerId : providers) { + System.out.println("Loading provider: " + providerId); + String type = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); + PidProviderFactory factory = pidProviderFactoryMap.get(type); + PidUtil.addToProviderList(factory.createPidProvider(providerId)); + } + } + + @AfterAll + public static void tearDownClass() throws Exception { + PidUtil.clearPidProviders(); } @BeforeEach @@ -81,29 +119,42 @@ public void testGetDoi() throws IOException { System.out.println("ex: " + ex); } } + @Test - public void testGetPermaLink() throws IOException { + public void testFactories() throws IOException { PidProvider p = PidUtil.getPidProvider("perma1"); - GlobalId pid = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE-5A-XN55", "-", p.getUrlPrefix(), "perma1"); - System.out.println(pid.asString()); - System.out.println(pid.asURL()); - + assertEquals("perma 1", p.getLabel()); + assertEquals(PermaLinkPidProvider.PERMA_PROTOCOL, p.getProtocol()); + assertEquals("DANSLINK", p.getAuthority()); + assertEquals("QE", p.getShoulder()); + assertEquals("-", p.getSeparator()); + assertTrue(p.getUrlPrefix().startsWith(SystemConfig.getDataverseSiteUrlStatic())); + p = PidUtil.getPidProvider("perma2"); + assertTrue(p.getUrlPrefix().startsWith("https://example.org/123")); + } + + @Test + public void testPermaLinkParsing() throws IOException { + PidProvider p = PidUtil.getPidProvider("perma1"); - GlobalId pid2 = PidUtil.parseAsGlobalID(pid.asString()); - assertEquals(pid.asString(), pid2.asString()); - assertEquals("perma1", pid2.getProviderName()); - GlobalId pid3 = PidUtil.parseAsGlobalID(pid.asURL()); - assertEquals(pid.asString(), pid3.asString()); - assertEquals("perma1", pid3.getProviderName()); + String pid1String = "perma:DANSLINK-QE-5A-XN55"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals("perma1", pid2.getProviderId()); + assertEquals(SystemConfig.getDataverseSiteUrlStatic() + "/citation?persistentId=" + pid1String, pid2.asURL()); + assertEquals("DANSLINK", pid2.getAuthority()); + assertEquals(PermaLinkPidProvider.PERMA_PROTOCOL, pid2.getProtocol()); + GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); + assertEquals(pid1String, pid3.asString()); + assertEquals("perma1", pid3.getProviderId()); - p = PidUtil.getPidProvider("perma2"); - GlobalId pid5 = new GlobalId(PermaLinkPidProvider.PERMA_PROTOCOL,"DANSLINK","QE/5A-XN55", "/", p.getUrlPrefix(), "perma2"); - GlobalId pid6 = PidUtil.parseAsGlobalID(pid5.asString()); - assertEquals("perma2", pid6.getProviderName()); - assertEquals(pid5.asString(), pid6.asString()); - + String pid4String = "perma:DANSLINK/QE-5A-XN55"; + GlobalId pid5 = PidUtil.parseAsGlobalID(pid4String); + assertEquals("perma2", pid5.getProviderId()); + assertEquals(pid4String, pid5.asString()); + assertEquals("https://example.org/123/citation?persistentId=" + pid4String, pid5.asURL()); } From 3f064a68e2d29328354a587bea988ae54cc9d2cc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 5 Jan 2024 18:16:53 -0500 Subject: [PATCH 025/113] first datacite parsing test/fix id in pid --- .../pidproviders/DataCiteDOIProvider.java | 2 +- .../dataverse/pidproviders/PidUtilTest.java | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index 1f89aa15ca8..5490eefcb26 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -257,7 +257,7 @@ public boolean publicizeIdentifier(DvObject dvObject) { @Override public List getProviderInformation() { - return List.of("DataCite", "https://status.datacite.org"); + return List.of(getId(), "https://status.datacite.org"); } @Override diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 47b3047f28a..f9a5a50cf62 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -52,7 +52,7 @@ @JvmSetting(key = JvmSettings.PERMALINK_BASE_URL, value = "https://example.org/123", varArgs = "perma2") // Datacite 1 @JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "dataCite 1", varArgs = "dc1") -@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = DataCiteDOIProvider.TYPE, varArgs = "dc1") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5072", varArgs = "dc1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK2", varArgs = "dc1") @JvmSetting(key = JvmSettings.DATACITE_MDS_API_URL, value = "https://mds.test.api.org/", varArgs = "dc1") @@ -137,19 +137,22 @@ public void testFactories() throws IOException { @Test public void testPermaLinkParsing() throws IOException { - PidProvider p = PidUtil.getPidProvider("perma1"); - + //Verify that we can parse a valid perma link associated with perma1 String pid1String = "perma:DANSLINK-QE-5A-XN55"; GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); assertEquals(pid1String, pid2.asString()); + //Check that it was parsed by perma1 and that the URL is correct, etc assertEquals("perma1", pid2.getProviderId()); assertEquals(SystemConfig.getDataverseSiteUrlStatic() + "/citation?persistentId=" + pid1String, pid2.asURL()); assertEquals("DANSLINK", pid2.getAuthority()); assertEquals(PermaLinkPidProvider.PERMA_PROTOCOL, pid2.getProtocol()); + + //Verify that parsing the URL form works GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); assertEquals(pid1String, pid3.asString()); assertEquals("perma1", pid3.getProviderId()); + //Repeat the basics with a permalink associated with perma2 String pid4String = "perma:DANSLINK/QE-5A-XN55"; GlobalId pid5 = PidUtil.parseAsGlobalID(pid4String); assertEquals("perma2", pid5.getProviderId()); @@ -157,5 +160,20 @@ public void testPermaLinkParsing() throws IOException { assertEquals("https://example.org/123/citation?persistentId=" + pid4String, pid5.asURL()); } + + @Test + public void testDOIParsing() throws IOException { + + String pid1String = "doi:10.5072/FK2ABCDEF"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals("dc1", pid2.getProviderId()); + assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); + assertEquals("10.5072", pid2.getAuthority()); + assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); + GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); + assertEquals(pid1String, pid3.asString()); + assertEquals("dc1", pid3.getProviderId()); + } } From 359f8e467ac73fd5f4c2c01a8654f3f788669f3c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 8 Jan 2024 17:56:23 -0500 Subject: [PATCH 026/113] rename class --- ...PersistentIdentifierProviderTest.java => PidProviderTest.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/java/edu/harvard/iq/dataverse/pidproviders/{PersistentIdentifierProviderTest.java => PidProviderTest.java} (100%) diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PersistentIdentifierProviderTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java similarity index 100% rename from src/test/java/edu/harvard/iq/dataverse/pidproviders/PersistentIdentifierProviderTest.java rename to src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java From 45bc5d6c3af0834c9b4df49917719a854b02c003 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 8 Jan 2024 17:56:53 -0500 Subject: [PATCH 027/113] move auth/shoulder check to lower level method --- .../pidproviders/AbstractPidProvider.java | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index f7ab4cbee29..0440397db38 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -26,6 +26,7 @@ public abstract class AbstractPidProvider implements PidProvider { private static final Logger logger = Logger.getLogger(AbstractPidProvider.class.getCanonicalName()); public static String UNAVAILABLE = ":unav"; + public static final String SEPARATOR = "/"; PidProviderFactoryBean pidProviderService; @@ -63,7 +64,12 @@ public abstract class AbstractPidProvider implements PidProvider { this.shoulder = shoulder; this.identifierGenerationStyle = identifierGenerationStyle; this.datafilePidFormat = datafilePidFormat; - this.managedSet = new HashSet(Arrays.asList(managedList.split(",\\s"))); + logger.info("managedList in " + getId() + ": " + managedList); + this.managedSet = new HashSet(Arrays.asList(managedList.split(",\\s"))); + Iterator iter = managedSet.iterator(); + while (iter.hasNext()) { + logger.info("managedSet in " + getId() + ": " + iter.next()); + } this.excludedSet = new HashSet(Arrays.asList(excludedList.split(",\\s"))); } @@ -288,22 +294,6 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { if (PidProvider.testforNullTerminator(identifier)) { return null; } - //Check authority/identifier if this is a provider that manages specific identifiers - // /is not one of the unmanaged providers that has null authority - if (getAuthority() != null) { - - String cleanIdentifier = authority + getSeparator() + identifier; - /* - * Test if this provider manages this identifier - return null if it does not It - * does if ((the identifier's authority and shoulder match the provider's), or - * the identifier in on the managed set), and the identifier is not in the - * excluded set. - */ - if (!(((authority.equals(getAuthority()) && identifier.startsWith(getShoulder())) - || getManagedSet().contains(cleanIdentifier)) && !getExcludedSet().contains(cleanIdentifier))) { - return null; - } - } } else { logger.log(Level.INFO, "Error parsing identifier: {0}: '':/'' not found in string", @@ -318,6 +308,27 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden if(!PidProvider.isValidGlobalId(protocol, authority, identifier)) { return null; } + //Check authority/identifier if this is a provider that manages specific identifiers + // /is not one of the unmanaged providers that has null authority + if (getAuthority() != null) { + + String cleanIdentifier = protocol + ":" + authority + getSeparator() + identifier; + /* + * Test if this provider manages this identifier - return null if it does not It + * does if ((the identifier's authority and shoulder match the provider's), or + * the identifier in on the managed set), and the identifier is not in the + * excluded set. + */ + logger.info("managed set size for " + getId() + ": " + getManagedSet().size()); + logger.info("clean pid in " + getId() + ": " + cleanIdentifier); + + logger.info("managed in " + getId() + ": " + getManagedSet().contains(cleanIdentifier)); + + if (!(((authority.equals(getAuthority()) && identifier.startsWith(getShoulder())) + || getManagedSet().contains(cleanIdentifier)) && !getExcludedSet().contains(cleanIdentifier))) { + return null; + } + } return new GlobalId(protocol, authority, identifier, getSeparator(), getUrlPrefix(), getProviderInformation().get(0)); } @@ -325,7 +336,7 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden public String getSeparator() { //The standard default - return "/"; + return SEPARATOR; } @Override @@ -335,7 +346,7 @@ public String generateDataFileIdentifier(DataFile datafile) { String prepend = ""; if (doiDataFileFormat.equals(SystemConfig.DataFilePIDFormat.DEPENDENT.toString())){ //If format is dependent then pre-pend the dataset identifier - prepend = datafile.getOwner().getIdentifier() + "/"; + prepend = datafile.getOwner().getIdentifier() + SEPARATOR; datafile.setProtocol(datafile.getOwner().getProtocol()); datafile.setAuthority(datafile.getOwner().getAuthority()); } else { @@ -779,4 +790,9 @@ public String getId() { public String getLabel() { return label; } + + @Override + public boolean canCreatePidsLike(GlobalId pid) { + return canManagePID() && !managedSet.contains(pid.asString()); + } } From 2b2290cdb9d8d1d641024f61e8844bc032e54379 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 8 Jan 2024 17:59:06 -0500 Subject: [PATCH 028/113] fix ids, fix managed list optional in fake --- .../iq/dataverse/pidproviders/EZIdDOIProvider.java | 9 +-------- .../iq/dataverse/pidproviders/FakeDOIProvider.java | 2 +- .../iq/dataverse/pidproviders/FakeProviderFactory.java | 4 ++-- .../iq/dataverse/pidproviders/HandlePidProvider.java | 2 +- .../iq/dataverse/pidproviders/UnmanagedDOIProvider.java | 7 +------ .../pidproviders/UnmanagedHandlePidProvider.java | 7 +------ .../pidproviders/UnmanagedPermaLinkPidProvider.java | 2 +- 7 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java index c161c4bf9d8..31b23080526 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java @@ -231,7 +231,7 @@ private boolean updateIdentifierStatus(DvObject dvObject, String statusIn) { @Override public List getProviderInformation(){ - return List.of("EZID", this.baseUrl); + return List.of(getId(), this.baseUrl); } @Override @@ -287,12 +287,5 @@ protected String getProviderKeyName() { public String getProviderType() { return TYPE; } - - @Override - public String getId() { - // TODO Auto-generated method stub - return null; - } - } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java index b900897b6ef..df57677e136 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java @@ -39,7 +39,7 @@ public boolean registerWhenPublished() { @Override public List getProviderInformation() { - return List.of("FAKE", "https://dataverse.org"); + return List.of(getId(), "https://dataverse.org"); } @Override diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java index 74a865f7e1b..6304874243b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java @@ -19,8 +19,8 @@ public PidProvider createPidProvider(String providerId) { .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.lookup(providerId); - String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookup(providerId); + String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse("");; + String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse("");; return new FakeDOIProvider(providerId, providerLabel, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index fa06d0214a4..71b5582aa9d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -387,7 +387,7 @@ private boolean updateIdentifierStatus(DvObject dvObject, String statusIn) { @Override public List getProviderInformation(){ - return List.of("Handle", "https://hdl.handle.net"); + return List.of(getId(), "https://hdl.handle.net"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index ec0776312aa..0423696e4ae 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -65,7 +65,7 @@ public boolean publicizeIdentifier(DvObject dvObject) { @Override public List getProviderInformation() { - return List.of("UnmanagedDOIProvider", ""); + return List.of(getId(), ""); } @Override @@ -73,11 +73,6 @@ public String getProviderType() { return "unamagedDOI"; } - @Override - public String getId() { - return ID; - } - // PID recognition // Done by DOIProvider diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java index 5c1179599e3..c7e6a9a773d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java @@ -60,7 +60,7 @@ public void deleteIdentifier(DvObject dvObject) throws Exception { @Override public List getProviderInformation() { - return List.of("UnmanagedHandle", ""); + return List.of(getId(), ""); } @Override @@ -110,9 +110,4 @@ public String getUrlPrefix() { public String getProviderType() { return "unamagedHandle"; } - - @Override - public String getId() { - return ID; - } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java index 3b7065acca9..e2e668ef229 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java @@ -58,7 +58,7 @@ public void deleteIdentifier(DvObject dvObject) throws Exception { @Override public List getProviderInformation() { - return List.of("UnmanagedPermaLink", ""); + return List.of(getId(), ""); } @Override From ed71ab750b7afbe13c7c3889f05f79e145747e7d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 8 Jan 2024 17:59:32 -0500 Subject: [PATCH 029/113] add effective pid generator logic --- .../iq/dataverse/DvObjectContainer.java | 72 +++++++++++++++++++ .../iq/dataverse/DvObjectServiceBean.java | 22 +++++- .../dataverse/pidproviders/PidProvider.java | 2 + .../pidproviders/PidProviderFactoryBean.java | 19 ++++- .../iq/dataverse/pidproviders/PidUtil.java | 31 +++++--- .../iq/dataverse/settings/JvmSettings.java | 1 + 6 files changed, 135 insertions(+), 12 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java index 82057315fbb..6c03fd1eac9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java @@ -1,14 +1,22 @@ package edu.harvard.iq.dataverse; import edu.harvard.iq.dataverse.dataaccess.DataAccess; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.storageuse.StorageUse; import edu.harvard.iq.dataverse.util.SystemConfig; +import edu.harvard.iq.dataverse.util.json.JsonUtil; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; import jakarta.persistence.CascadeType; import java.util.Optional; +import java.util.logging.Logger; import jakarta.persistence.MappedSuperclass; import jakarta.persistence.OneToOne; +import jakarta.persistence.Transient; + import org.apache.commons.lang3.StringUtils; /** @@ -42,6 +50,11 @@ public boolean isEffectivelyPermissionRoot() { private String metadataLanguage=null; private Boolean guestbookAtRequest = null; + + private String pidGeneratorSpecs = null; + + @Transient + private PidProvider pidGenerator = null; @OneToOne(mappedBy = "dvObjectContainer",cascade={ CascadeType.REMOVE, CascadeType.PERSIST}, orphanRemoval=true) private StorageUse storageUse; @@ -175,4 +188,63 @@ public void setCurationLabelSetName(String setName) { public void setStorageUse(StorageUse storageUse) { this.storageUse = storageUse; } + + + /* Dataverse collections and dataset can be configured to use different PidProviders as PID generators for contained objects (datasets or data files). + * This mechanism is similar to others except that the stored value is a JSON object defining the protocol, authority, shoulder, and, optionally, the separator for the PidProvider. + */ + + public String getPidGeneratorSpecs() { + return pidGeneratorSpecs; + } + + public void setPidGeneratorSpecs(String pidGeneratorSpecs) { + this.pidGeneratorSpecs = pidGeneratorSpecs; + } + + public PidProvider getPidGenerator() { + return pidGenerator; + } + + public void setPidGenerator(PidProvider pidGenerator) { + this.pidGenerator = pidGenerator; + JsonObjectBuilder job = jakarta.json.Json.createObjectBuilder(); + if (pidGenerator != null) { + this.pidGeneratorSpecs = job.add("protocol", pidGenerator.getProtocol()) + .add("authority", pidGenerator.getAuthority()).add("shoulder", pidGenerator.getShoulder()) + .add("separator", pidGenerator.getSeparator()).build().toString(); + } else { + this.pidGeneratorSpecs = null; + } + } + + public PidProvider getEffectivePidGenerator() { + PidProvider pidGenerator = getPidGenerator(); + if (pidGenerator == null) { + String specs = getPidGeneratorSpecs(); + if (StringUtils.isBlank(specs)) { + GlobalId pid = getGlobalId(); + if ((pid != null) && PidUtil.getPidProvider(pid.getProviderId()).canCreatePidsLike(pid)) { + pidGenerator = PidUtil.getPidProvider(pid.getProviderId()); + } else { + if (getOwner() != null) { + pidGenerator = getOwner().getEffectivePidGenerator(); + } + } + } else { + JsonObject providerSpecs = JsonUtil.getJsonObject(specs); + if (providerSpecs.containsKey("separator")) { + pidGenerator = PidUtil.getPidProvider(providerSpecs.getString("protocol"), + providerSpecs.getString("authority"), providerSpecs.getString("shoulder"), + providerSpecs.getString("separator")); + } else { + pidGenerator = PidUtil.getPidProvider(providerSpecs.getString("protocol"), + providerSpecs.getString("authority"), providerSpecs.getString("shoulder")); + } + } + } + setPidGenerator(pidGenerator); + return pidGenerator; + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java index d4219c36149..0ba887196f8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java @@ -1,8 +1,9 @@ package edu.harvard.iq.dataverse; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; import edu.harvard.iq.dataverse.pidproviders.PidUtil; - import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; @@ -12,6 +13,8 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; + +import jakarta.ejb.EJB; import jakarta.ejb.Stateless; import jakarta.ejb.TransactionAttribute; import static jakarta.ejb.TransactionAttributeType.REQUIRES_NEW; @@ -38,6 +41,9 @@ public class DvObjectServiceBean implements java.io.Serializable { @PersistenceContext(unitName = "VDCNet-ejbPU") private EntityManager em; + @EJB + PidProviderFactoryBean pidProviderFactoryBean; + private static final Logger logger = Logger.getLogger(DvObjectServiceBean.class.getCanonicalName()); /** * @param dvoc The object we check @@ -389,4 +395,18 @@ public String generateNewIdentifierByStoredProcedure() { return (String) query.getOutputParameterValue(1); } + /** Backward-compatibility method to get the effective pid generator for a DvObjectContainer. + * If the dvObjectContainer method fails, this method will check for the old global default settings. + * + * If/when those are no longer supported, this method can be removed. + * + */ + public PidProvider getEffectivePidGenerator(DvObjectContainer dvObjectContainer) { + PidProvider pidGenerator = dvObjectContainer.getEffectivePidGenerator(); + if(pidGenerator == null) { + pidGenerator = pidProviderFactoryBean.getDefaultPidGenerator(); + } + return pidGenerator; + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index fa96f95e059..a8368ea2a56 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -179,4 +179,6 @@ static boolean checkDOIAuthority(String doiAuthority){ Set getExcludedSet(); + boolean canCreatePidsLike(GlobalId pid); + } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 3e77acae9ad..fb8457df6c3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -145,7 +145,7 @@ String generateNewIdentifierByStoredProcedure() { * @param dvObject * @return - a PidProvider for the object (may be one of the Unmanaged providers) */ - + @Deprecated public PidProvider getPidProvider(DvObject dvObject) { GlobalId pid = dvObject.getGlobalId(); if (pid != null) { @@ -164,4 +164,21 @@ public PidProvider getPidProvider(DvObject dvObject) { } } + + public PidProvider getDefaultPidGenerator() { + Optional pidProviderDefaultId = JvmSettings.PID_DEFAULT_PROVIDER.lookupOptional(String.class); + if(pidProviderDefaultId.isPresent()) { + return PidUtil.getPidProvider(pidProviderDefaultId.get()); + } else { + String nonNullDefaultIfKeyNotFound = ""; + String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol, + nonNullDefaultIfKeyNotFound); + String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority, + nonNullDefaultIfKeyNotFound); + String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder, + nonNullDefaultIfKeyNotFound); + + return PidUtil.getPidProvider(protocol, authority, shoulder); + } + } } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 7bfef31a5b4..4d26202e1f1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -234,13 +234,33 @@ public static PidProvider getPidProvider(String name) { return null; } + + + /** + * Method to clear all managed/unmanaged PidProviders. Only for testing as these + * lists are only loaded once by the @Stateless PidProviderFactoryBean in Dataverse. + */ + public static void clearPidProviders() { + providerMap.clear(); + unmanagedProviderMap.clear(); + } + + public static PidProvider getDefaultPidGenerator() { + // TODO Auto-generated method stub + return null; + } + /** * Get a PidProvider by protocol/authority/shoulder. */ public static PidProvider getPidProvider(String protocol, String authority, String shoulder) { + return getPidProvider(protocol, authority, shoulder, AbstractPidProvider.SEPARATOR); + } + + public static PidProvider getPidProvider(String protocol, String authority, String shoulder, String separator) { for (PidProvider pidProvider : providerMap.values()) { if (protocol.equals(pidProvider.getProtocol()) && authority.equals(pidProvider.getAuthority()) - && shoulder.equals(pidProvider.getShoulder())) { + && shoulder.equals(pidProvider.getShoulder()) && separator.equals(pidProvider.getSeparator())) { return pidProvider; } } @@ -251,13 +271,4 @@ public static PidProvider getPidProvider(String protocol, String authority, Stri } return null; } - - /** - * Method to clear all managed/unmanaged PidProviders. Only for testing as these - * lists are only loaded once by the @Stateless PidProviderFactoryBean in Dataverse. - */ - public static void clearPidProviders() { - providerMap.clear(); - unmanagedProviderMap.clear(); - } } diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index c2db29d2e48..c6d04f4ec4b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -92,6 +92,7 @@ public enum JvmSettings { // PERSISTENT IDENTIFIER SETTINGS SCOPE_PID(PREFIX, "pid"), PID_PROVIDERS(SCOPE_PID, "providers"), + PID_DEFAULT_PROVIDER(SCOPE_PID, "default-provider"), PROVIDERS_DIRECTORY(SCOPE_PID, "provider-implementations-directory"), SCOPE_PID_PROVIDER(SCOPE_PID), PID_PROVIDER_TYPE(SCOPE_PID_PROVIDER, "type"), From 342cf80b74c98c146e9eceb73be93c788c244c87 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 8 Jan 2024 18:00:04 -0500 Subject: [PATCH 030/113] add effective pid generator tests --- .../pidproviders/PidProviderTest.java | 67 +-------- .../dataverse/pidproviders/PidUtilTest.java | 139 +++++++++++++++++- 2 files changed, 133 insertions(+), 73 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java index a3f23940cc4..593396dd467 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java @@ -27,7 +27,7 @@ * @author michael */ @ExtendWith(MockitoExtension.class) -public class PersistentIdentifierProviderTest { +public class PidProviderTest { @Mock private SettingsServiceBean settingsServiceBean; @@ -48,68 +48,5 @@ public PidProviderFactoryBean pidProviderFactory() { }; } - /** - * Test of getBean method, of class PersistentIdentifierServiceBean. - */ - /* - @Test - public void testGetBean_String_CommandContext_OK() { - ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "EZID"); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("EZID"); - - assertEquals(ezidServiceBean, - PidProvider.getBean("doi", ctxt)); - - ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "DataCite"); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("DataCite"); - - assertEquals(dataCiteServiceBean, - PidProvider.getBean("doi", ctxt)); - - ctxt.settings().setValueForKey(SettingsServiceBean.Key.DoiProvider, "FAKE"); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("FAKE"); - - assertEquals(fakePidProviderServiceBean, - PidProvider.getBean("doi", ctxt)); - - assertEquals(hdlServiceBean, - PidProvider.getBean("hdl", ctxt)); - - assertEquals(permaLinkServiceBean, - PidProvider.getBean("perma", ctxt)); - } - */ - /* - @Test - public void testGetBean_String_CommandContext_BAD() { - ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "non-existent-provider"); - assertNull(PidProvider.getBean("doi", ctxt)); - - - assertNull(PidProvider.getBean("non-existent-protocol", ctxt)); - } -*/ - /** - * Test of getBean method, of class PersistentIdentifierServiceBean. - */ - /* - @Test - public void testGetBean_CommandContext() { - ctxt.settings().setValueForKey( SettingsServiceBean.Key.Protocol, "doi"); - ctxt.settings().setValueForKey( SettingsServiceBean.Key.DoiProvider, "EZID"); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider, "")).thenReturn("EZID"); - - assertEquals(ezidServiceBean, - PidProvider.getBean("doi", ctxt)); - - ctxt.settings().setValueForKey( SettingsServiceBean.Key.Protocol, "hdl"); - assertEquals(hdlServiceBean, - PidProvider.getBean("hdl", ctxt)); - - ctxt.settings().setValueForKey( SettingsServiceBean.Key.Protocol, "perma"); - assertEquals(permaLinkServiceBean, - PidProvider.getBean("perma", ctxt)); - } - -*/ + } diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index f9a5a50cf62..632424f963e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -1,5 +1,7 @@ package edu.harvard.iq.dataverse.pidproviders; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; @@ -15,6 +17,7 @@ import java.util.List; import java.util.Map; +import jakarta.json.Json; import jakarta.json.JsonObjectBuilder; import jakarta.ws.rs.NotFoundException; import org.junit.jupiter.api.Disabled; @@ -32,9 +35,7 @@ import static org.junit.jupiter.api.Assertions.*; -/** - * Useful for testing but requires DataCite credentials, etc. - */ + @ExtendWith(MockitoExtension.class) @LocalJvmSettings //Perma 1 @@ -53,14 +54,49 @@ // Datacite 1 @JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "dataCite 1", varArgs = "dc1") @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = DataCiteDOIProvider.TYPE, varArgs = "dc1") -@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5072", varArgs = "dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5073", varArgs = "dc1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK2", varArgs = "dc1") -@JvmSetting(key = JvmSettings.DATACITE_MDS_API_URL, value = "https://mds.test.api.org/", varArgs = "dc1") +@JvmSetting(key = JvmSettings.DATACITE_MDS_API_URL, value = "https://mds.test.datacite.org/", varArgs = "dc1") @JvmSetting(key = JvmSettings.DATACITE_REST_API_URL, value = "https://api.test.datacite.org", varArgs ="dc1") @JvmSetting(key = JvmSettings.DATACITE_USERNAME, value = "test", varArgs ="dc1") @JvmSetting(key = JvmSettings.DATACITE_PASSWORD, value = "changeme", varArgs ="dc1") +//Datacite 2 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "dataCite 2", varArgs = "dc2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = DataCiteDOIProvider.TYPE, varArgs = "dc2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5072", varArgs = "dc2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK3", varArgs = "dc2") +@JvmSetting(key = JvmSettings.DATACITE_MDS_API_URL, value = "https://mds.test.datacite.org/", varArgs = "dc2") +@JvmSetting(key = JvmSettings.DATACITE_REST_API_URL, value = "https://api.test.datacite.org", varArgs ="dc2") +@JvmSetting(key = JvmSettings.DATACITE_USERNAME, value = "test2", varArgs ="dc2") +@JvmSetting(key = JvmSettings.DATACITE_PASSWORD, value = "changeme2", varArgs ="dc2") +//EZID 1 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "EZId 1", varArgs = "ez1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = EZIdDOIProvider.TYPE, varArgs = "ez1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5072", varArgs = "ez1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK2", varArgs = "ez1") +@JvmSetting(key = JvmSettings.EZID_API_URL, value = "https://ezid.cdlib.org/", varArgs = "ez1") +@JvmSetting(key = JvmSettings.EZID_USERNAME, value = "apitest", varArgs ="ez1") +@JvmSetting(key = JvmSettings.EZID_PASSWORD, value = "apitest", varArgs ="ez1") +//FAKE 1 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "FAKE 1", varArgs = "fake1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = FakeDOIProvider.TYPE, varArgs = "fake1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5074", varArgs = "fake1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK", varArgs = "fake1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_MANAGED_LIST, value = "doi:10.5073/FK3ABCDEF", varArgs ="fake1") + +//HANDLE 1 +@JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "HDL 1", varArgs = "hdl1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = HandlePidProvider.TYPE, varArgs = "hdl1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "20.500.1234", varArgs = "hdl1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "", varArgs = "hdl1") +@JvmSetting(key = JvmSettings.HANDLENET_AUTH_HANDLE, value = "20.500.1234/ADMIN", varArgs ="hdl1") +@JvmSetting(key = JvmSettings.HANDLENET_INDEPENDENT_SERVICE, value = "true", varArgs ="hdl1") +@JvmSetting(key = JvmSettings.HANDLENET_INDEX, value = "1", varArgs ="hdl1") +@JvmSetting(key = JvmSettings.HANDLENET_KEY_PASSPHRASE, value = "passphrase", varArgs ="hdl1") +@JvmSetting(key = JvmSettings.HANDLENET_KEY_PATH, value = "/tmp/cred", varArgs ="hdl1") + //List to instantiate -@JvmSetting(key = JvmSettings.PID_PROVIDERS, value = "perma1, perma2, dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDERS, value = "perma1, perma2, dc1, dc2, ez1, fake1, hdl1") public class PidUtilTest { @@ -90,6 +126,8 @@ public static void setUpClass() throws Exception { PidProviderFactory factory = pidProviderFactoryMap.get(type); PidUtil.addToProviderList(factory.createPidProvider(providerId)); } + PidUtil.addAllToUnmanagedProviderList(Arrays.asList(new UnmanagedDOIProvider(), + new UnmanagedHandlePidProvider(), new UnmanagedPermaLinkPidProvider())); } @AfterAll @@ -104,6 +142,9 @@ public void initMocks() { // Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("DANSLINK"); } + /** + * Useful for testing but requires DataCite credentials, etc. + */ @Disabled @Test public void testGetDoi() throws IOException { @@ -132,6 +173,8 @@ public void testFactories() throws IOException { assertTrue(p.getUrlPrefix().startsWith(SystemConfig.getDataverseSiteUrlStatic())); p = PidUtil.getPidProvider("perma2"); assertTrue(p.getUrlPrefix().startsWith("https://example.org/123")); + p = PidUtil.getPidProvider("dc2"); + assertEquals("FK3", p.getShoulder()); } @@ -164,16 +207,96 @@ public void testPermaLinkParsing() throws IOException { @Test public void testDOIParsing() throws IOException { - String pid1String = "doi:10.5072/FK2ABCDEF"; + String pid1String = "doi:10.5073/FK2ABCDEF"; GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); assertEquals(pid1String, pid2.asString()); assertEquals("dc1", pid2.getProviderId()); assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); - assertEquals("10.5072", pid2.getAuthority()); + assertEquals("10.5073", pid2.getAuthority()); assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); assertEquals(pid1String, pid3.asString()); assertEquals("dc1", pid3.getProviderId()); + + String pid4String = "doi:10.5072/FK3ABCDEF"; + GlobalId pid4 = PidUtil.parseAsGlobalID(pid4String); + assertEquals(pid4String, pid4.asString()); + assertEquals("dc2", pid4.getProviderId()); + + String pid5String = "doi:10.5072/FK2ABCDEF"; + GlobalId pid5 = PidUtil.parseAsGlobalID(pid5String); + assertEquals(pid5String, pid5.asString()); + assertEquals("ez1", pid5.getProviderId()); + + String pid6String = "doi:10.5074/FKABCDEF"; + GlobalId pid6 = PidUtil.parseAsGlobalID(pid6String); + assertEquals(pid6String, pid6.asString()); + assertEquals("fake1", pid6.getProviderId()); + + } + + @Test + public void testHandleParsing() throws IOException { + + String pid1String = "hdl:20.500.1234/10052"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals("hdl1", pid2.getProviderId()); + assertEquals("https://hdl.handle.net/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); + assertEquals("20.500.1234", pid2.getAuthority()); + assertEquals(HandlePidProvider.HDL_PROTOCOL, pid2.getProtocol()); + GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); + assertEquals(pid1String, pid3.asString()); + assertEquals("hdl1", pid3.getProviderId()); + } + + @Test + public void testUnmanagedParsing() throws IOException { + + String pid1String = "hdl:20.500.3456/10052"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals("UnmanagedHandleProvider", pid2.getProviderId()); + assertEquals("https://hdl.handle.net/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); + assertEquals("20.500.3456", pid2.getAuthority()); + assertEquals(HandlePidProvider.HDL_PROTOCOL, pid2.getProtocol()); + GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); + assertEquals(pid1String, pid3.asString()); + assertEquals("UnmanagedHandleProvider", pid3.getProviderId()); + + String pid5String = "doi:10.6083/FK2ABCDEF"; + GlobalId pid5 = PidUtil.parseAsGlobalID(pid5String); + assertEquals(pid5String, pid5.asString()); + assertEquals("UnmanagedDOIProvider", pid5.getProviderId()); + } + + @Test + public void testFindingPidGenerators() throws IOException { + + Dataset dataset1 = new Dataset(); + Dataverse dataverse1 = new Dataverse(); + dataset1.setOwner(dataverse1); + String pidGeneratorSpecs = Json.createObjectBuilder().add("protocol", DOIProvider.DOI_PROTOCOL).add("authority","10.5072").add("shoulder", "FK2").build().toString(); + dataverse1.setPidGeneratorSpecs(pidGeneratorSpecs); + assertEquals(pidGeneratorSpecs, dataverse1.getPidGeneratorSpecs()); + assertEquals("ez1", dataverse1.getEffectivePidGenerator().getId()); + assertEquals("ez1", dataset1.getEffectivePidGenerator().getId()); + + dataset1.setAuthority("10.5073"); + dataset1.setProtocol(DOIProvider.DOI_PROTOCOL); + dataset1.setIdentifier("FK2ABCDEF"); + + dataset1.setPidGenerator(null); + assertEquals("dc1", dataset1.getGlobalId().getProviderId()); + assertEquals("dc1", dataset1.getEffectivePidGenerator().getId()); + + dataset1.setPidGenerator(null); + dataset1.setIdentifier("FK3ABCDEF"); + assertEquals("fake1", dataset1.getGlobalId().getProviderId()); + assertEquals("ez1", dataset1.getEffectivePidGenerator().getId()); + + + } } From 75beab53a15e1df25d6de1a185a6724264d14fdb Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 9 Jan 2024 10:22:59 -0500 Subject: [PATCH 031/113] fix param order --- .../iq/dataverse/pidproviders/DataCiteDOIProvider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index 5490eefcb26..6b714f9a755 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -43,9 +43,9 @@ public class DataCiteDOIProvider extends DOIProvider { private String username; private String password; - public DataCiteDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String managedList, - String excludedList, String identifierGenerationStyle, String datafilePidFormat, String mdsUrl, - String apiUrl, String username, String password) { + public DataCiteDOIProvider(String id, String label, String providerAuthority, String providerShoulder, + String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, + String mdsUrl, String apiUrl, String username, String password) { super(id, label, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.mdsUrl = mdsUrl; From 9a21d6c45ebe78a2f92dc9ab9ec8954e9a4ff4dc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 9 Jan 2024 10:23:54 -0500 Subject: [PATCH 032/113] fix perma handling of managed/excluded entries --- .../pidproviders/PermaLinkPidProvider.java | 22 ++++++++++++++++++- .../UnmanagedPermaLinkPidProvider.java | 21 ++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 92d88085f2c..9f48f39239e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -29,6 +29,7 @@ public class PermaLinkPidProvider extends AbstractPidProvider { public static final String PERMA_PROTOCOL = "perma"; public static final String TYPE = "perma"; + public static final String SEPARATOR = ""; // ToDo - remove @Deprecated @@ -36,7 +37,7 @@ public class PermaLinkPidProvider extends AbstractPidProvider { .orElse(SystemConfig.getDataverseSiteUrlStatic()); - private String separator = ""; + private String separator = SEPARATOR; private String baseUrl; @@ -123,6 +124,25 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { if (!PERMA_PROTOCOL.equals(protocol)) { return null; } + String cleanIdentifier = PERMA_PROTOCOL + ":" + identifierString; + // With permalinks, we have to check the sets before parsing since the permalinks in these sets could have different authority, spearator, and shoulders + if (getExcludedSet().contains(cleanIdentifier)) { + return null; + } + if(getManagedSet().contains(cleanIdentifier)) { + /** With a variable separator that could also be empty, there is no way to determine the authority and shoulder for an unknown permalink. + * Since knowing this split isn't relevant for permalinks except for minting, the code below just assumes the authority + * is the first 4 characters and that the separator and the shoulder are empty. + * If this is found to cause issues, users should be able to use a managed permalink provider as a work-around. The code here could + * be changed to allow default lengths for the authority, separator, and shoulder and/or to add a list of known (but unmanaged) authority, separator, shoulder combos. + */ + if(identifierString.length() < 4) { + return new GlobalId(protocol, "", identifierString, SEPARATOR, getUrlPrefix(), + getProviderInformation().get(0)); + } + return new GlobalId(protocol, identifierString.substring(0,4), identifierString.substring(4), SEPARATOR, getUrlPrefix(), + getProviderInformation().get(0)); + } String identifier = null; if (getAuthority() != null) { if (identifierString.startsWith(getAuthority())) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java index e2e668ef229..bfe43bd9448 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java @@ -14,11 +14,10 @@ * It does not implement any of the methods related to PID CRUD * */ -@Stateless public class UnmanagedPermaLinkPidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedPermaLinkPidProvider.class.getCanonicalName()); - private static final String ID = "UnmanagedPermaLinkProvider"; + static final String ID = "UnmanagedPermaLinkProvider"; public UnmanagedPermaLinkPidProvider() { // Also using ID as label @@ -76,8 +75,17 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { if (!PermaLinkPidProvider.PERMA_PROTOCOL.equals(protocol)) { return null; } - GlobalId globalId = super.parsePersistentId(protocol, identifierString); - return globalId; + /** With a variable separator that could also be empty, there is no way to determine the authority and shoulder for an unknown/unmanaged permalink. + * Since knowing this split isn't relevant for unmanaged permalinks, the code below just assumes the authority + * is the first 4 characters and that the separator and the shoulder are empty. + * If this is found to cause issues, users should be able to use a managed permalink provider as a work-around. The code here could + * be changed to allow default lengths for the authority, separator, and shoulder and/or to add a list of known (but unmanaged) authority, separator, shoulder combos. + */ + if(identifierString.length() < 4) { + logger.warning("A short unmanaged permalink was found - assuming the authority is empty: " + identifierString); + return super.parsePersistentId(protocol, "", identifierString); + } + return super.parsePersistentId(protocol, identifierString.substring(0, 4), identifierString.substring(4)); } @Override @@ -97,4 +105,9 @@ public String getUrlPrefix() { public String getProviderType() { return PermaLinkPidProvider.TYPE; } + + @Override + public String getSeparator() { + return PermaLinkPidProvider.SEPARATOR; + } } From 053050ccadd0845e85421d6928285a357075947e Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 9 Jan 2024 10:24:46 -0500 Subject: [PATCH 033/113] add managed/excluded tests, cleanup --- .../pidproviders/AbstractPidProvider.java | 31 ++++--- .../pidproviders/HandlePidProvider.java | 2 +- .../pidproviders/UnmanagedDOIProvider.java | 2 +- .../UnmanagedHandlePidProvider.java | 2 +- .../dataverse/pidproviders/PidUtilTest.java | 90 +++++++++++++++++-- 5 files changed, 103 insertions(+), 24 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 0440397db38..8e2b966d9d0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -64,14 +64,18 @@ public abstract class AbstractPidProvider implements PidProvider { this.shoulder = shoulder; this.identifierGenerationStyle = identifierGenerationStyle; this.datafilePidFormat = datafilePidFormat; - logger.info("managedList in " + getId() + ": " + managedList); this.managedSet = new HashSet(Arrays.asList(managedList.split(",\\s"))); - Iterator iter = managedSet.iterator(); - while (iter.hasNext()) { - logger.info("managedSet in " + getId() + ": " + iter.next()); - } this.excludedSet = new HashSet(Arrays.asList(excludedList.split(",\\s"))); - + if (logger.isLoggable(Level.FINE)) { + Iterator iter = managedSet.iterator(); + while (iter.hasNext()) { + logger.fine("managedSet in " + getId() + ": " + iter.next()); + } + iter = excludedSet.iterator(); + while (iter.hasNext()) { + logger.fine("excludedSet in " + getId() + ": " + iter.next()); + } + } } @Override @@ -314,15 +318,14 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden String cleanIdentifier = protocol + ":" + authority + getSeparator() + identifier; /* - * Test if this provider manages this identifier - return null if it does not It - * does if ((the identifier's authority and shoulder match the provider's), or - * the identifier in on the managed set), and the identifier is not in the - * excluded set. + * Test if this provider manages this identifier - return null if it does not. + * It does match if ((the identifier's authority and shoulder match the + * provider's), or the identifier is in the managed set), and, in either case, + * the identifier is not in the excluded set. */ - logger.info("managed set size for " + getId() + ": " + getManagedSet().size()); - logger.info("clean pid in " + getId() + ": " + cleanIdentifier); - - logger.info("managed in " + getId() + ": " + getManagedSet().contains(cleanIdentifier)); + logger.fine("clean pid in " + getId() + ": " + cleanIdentifier); + logger.fine("managed in " + getId() + ": " + getManagedSet().contains(cleanIdentifier)); + logger.fine("excluded from " + getId() + ": " + getExcludedSet().contains(cleanIdentifier)); if (!(((authority.equals(getAuthority()) && identifier.startsWith(getShoulder())) || getManagedSet().contains(cleanIdentifier)) && !getExcludedSet().contains(cleanIdentifier))) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index 71b5582aa9d..e8f9fa8eaab 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -387,7 +387,7 @@ private boolean updateIdentifierStatus(DvObject dvObject, String statusIn) { @Override public List getProviderInformation(){ - return List.of(getId(), "https://hdl.handle.net"); + return List.of(getId(), HDL_RESOLVER_URL); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java index 0423696e4ae..ebb76e00181 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java @@ -16,7 +16,7 @@ public class UnmanagedDOIProvider extends DOIProvider { - private static final String ID = "UnmanagedDOIProvider"; + static final String ID = "UnmanagedDOIProvider"; public UnmanagedDOIProvider() { //Also using ID as label diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java index c7e6a9a773d..b292785632a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java @@ -19,7 +19,7 @@ public class UnmanagedHandlePidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedHandlePidProvider.class.getCanonicalName()); - private static final String ID = "UnmanagedHandleProvider"; + static final String ID = "UnmanagedHandleProvider"; public UnmanagedHandlePidProvider() { // Also using ID as label diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 632424f963e..c01c0f52ba9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -44,11 +44,14 @@ @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma1") @JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "-", varArgs = "perma1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_EXCLUDED_LIST, value = "perma:DANSLINKQE123456, perma:bad, perma:LINKIT123456", varArgs ="perma1") + //Perma 2 @JvmSetting(key = JvmSettings.PID_PROVIDER_LABEL, value = "perma 2", varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = PermaLinkPidProvider.TYPE, varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "DANSLINK", varArgs = "perma2") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "QE", varArgs = "perma2") +@JvmSetting(key = JvmSettings.PID_PROVIDER_MANAGED_LIST, value = "perma:LINKIT/FK2ABCDEF", varArgs ="perma2") @JvmSetting(key = JvmSettings.PERMALINK_SEPARATOR, value = "/", varArgs = "perma2") @JvmSetting(key = JvmSettings.PERMALINK_BASE_URL, value = "https://example.org/123", varArgs = "perma2") // Datacite 1 @@ -56,6 +59,7 @@ @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = DataCiteDOIProvider.TYPE, varArgs = "dc1") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "10.5073", varArgs = "dc1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "FK2", varArgs = "dc1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_EXCLUDED_LIST, value = "doi:10.5073/FK2123456", varArgs ="dc1") @JvmSetting(key = JvmSettings.DATACITE_MDS_API_URL, value = "https://mds.test.datacite.org/", varArgs = "dc1") @JvmSetting(key = JvmSettings.DATACITE_REST_API_URL, value = "https://api.test.datacite.org", varArgs ="dc1") @JvmSetting(key = JvmSettings.DATACITE_USERNAME, value = "test", varArgs ="dc1") @@ -89,6 +93,7 @@ @JvmSetting(key = JvmSettings.PID_PROVIDER_TYPE, value = HandlePidProvider.TYPE, varArgs = "hdl1") @JvmSetting(key = JvmSettings.PID_PROVIDER_AUTHORITY, value = "20.500.1234", varArgs = "hdl1") @JvmSetting(key = JvmSettings.PID_PROVIDER_SHOULDER, value = "", varArgs = "hdl1") +@JvmSetting(key = JvmSettings.PID_PROVIDER_MANAGED_LIST, value = "hdl:20.20.20/FK2ABCDEF", varArgs ="hdl1") @JvmSetting(key = JvmSettings.HANDLENET_AUTH_HANDLE, value = "20.500.1234/ADMIN", varArgs ="hdl1") @JvmSetting(key = JvmSettings.HANDLENET_INDEPENDENT_SERVICE, value = "true", varArgs ="hdl1") @JvmSetting(key = JvmSettings.HANDLENET_INDEX, value = "1", varArgs ="hdl1") @@ -253,23 +258,91 @@ public void testHandleParsing() throws IOException { @Test public void testUnmanagedParsing() throws IOException { - + // A handle managed not managed in the hdl1 provider String pid1String = "hdl:20.500.3456/10052"; GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); assertEquals(pid1String, pid2.asString()); - assertEquals("UnmanagedHandleProvider", pid2.getProviderId()); - assertEquals("https://hdl.handle.net/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); + //Only parsed by the unmanaged provider + assertEquals(UnmanagedHandlePidProvider.ID, pid2.getProviderId()); + assertEquals(HandlePidProvider.HDL_RESOLVER_URL + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); assertEquals("20.500.3456", pid2.getAuthority()); assertEquals(HandlePidProvider.HDL_PROTOCOL, pid2.getProtocol()); GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); assertEquals(pid1String, pid3.asString()); - assertEquals("UnmanagedHandleProvider", pid3.getProviderId()); + assertEquals(UnmanagedHandlePidProvider.ID, pid3.getProviderId()); + //Same for DOIs String pid5String = "doi:10.6083/FK2ABCDEF"; GlobalId pid5 = PidUtil.parseAsGlobalID(pid5String); assertEquals(pid5String, pid5.asString()); - assertEquals("UnmanagedDOIProvider", pid5.getProviderId()); + assertEquals(UnmanagedDOIProvider.ID, pid5.getProviderId()); + + //And Permalinks + String pid6String = "perma:NOTDANSQEABCDEF"; + GlobalId pid6 = PidUtil.parseAsGlobalID(pid6String); + assertEquals(pid6String, pid6.asString()); + assertEquals(UnmanagedPermaLinkPidProvider.ID, pid6.getProviderId()); + + } + + @Test + public void testExcludedSetParsing() throws IOException { + + String pid1String = "doi:10.5073/FK2123456"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals(UnmanagedDOIProvider.ID, pid2.getProviderId()); + assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); + assertEquals("10.5073", pid2.getAuthority()); + assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); + GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); + assertEquals(pid1String, pid3.asString()); + assertEquals(UnmanagedDOIProvider.ID, pid3.getProviderId()); + + String pid4String = "perma:bad"; + GlobalId pid4 = PidUtil.parseAsGlobalID(pid4String); + assertEquals(pid4String, pid4.asString()); + assertEquals(UnmanagedPermaLinkPidProvider.ID, pid4.getProviderId()); + + String pid5String = "perma:DANSLINKQE123456"; + GlobalId pid5 = PidUtil.parseAsGlobalID(pid5String); + assertEquals(pid5String, pid5.asString()); + assertEquals(UnmanagedPermaLinkPidProvider.ID, pid5.getProviderId()); + + String pid6String = "perma:LINKIT123456"; + GlobalId pid6 = PidUtil.parseAsGlobalID(pid6String); + assertEquals(pid6String, pid6.asString()); + assertEquals(UnmanagedPermaLinkPidProvider.ID, pid6.getProviderId()); + + + } + + @Test + public void testManagedSetParsing() throws IOException { + + String pid1String = "doi:10.5073/FK3ABCDEF"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals("fake1", pid2.getProviderId()); + assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); + assertEquals("10.5073", pid2.getAuthority()); + assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); + GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); + assertEquals(pid1String, pid3.asString()); + assertEquals("fake1", pid3.getProviderId()); + assertFalse(PidUtil.getPidProvider(pid3.getProviderId()).canCreatePidsLike(pid3)); + + String pid4String = "hdl:20.20.20/FK2ABCDEF"; + GlobalId pid4 = PidUtil.parseAsGlobalID(pid4String); + assertEquals(pid4String, pid4.asString()); + assertEquals("hdl1", pid4.getProviderId()); + assertFalse(PidUtil.getPidProvider(pid4.getProviderId()).canCreatePidsLike(pid4)); + String pid5String = "perma:LINKIT/FK2ABCDEF"; + GlobalId pid5 = PidUtil.parseAsGlobalID(pid5String); + assertEquals(pid5String, pid5.asString()); + assertEquals("perma2", pid5.getProviderId()); + assertFalse(PidUtil.getPidProvider(pid5.getProviderId()).canCreatePidsLike(pid5)); } @Test @@ -279,20 +352,23 @@ public void testFindingPidGenerators() throws IOException { Dataverse dataverse1 = new Dataverse(); dataset1.setOwner(dataverse1); String pidGeneratorSpecs = Json.createObjectBuilder().add("protocol", DOIProvider.DOI_PROTOCOL).add("authority","10.5072").add("shoulder", "FK2").build().toString(); + //Set a PID generator on the parent dataverse1.setPidGeneratorSpecs(pidGeneratorSpecs); assertEquals(pidGeneratorSpecs, dataverse1.getPidGeneratorSpecs()); + //Verify that the parent's PID generator is the effective one assertEquals("ez1", dataverse1.getEffectivePidGenerator().getId()); assertEquals("ez1", dataset1.getEffectivePidGenerator().getId()); - + //Change dataset to have a provider and verify that it is used instead of any effective one dataset1.setAuthority("10.5073"); dataset1.setProtocol(DOIProvider.DOI_PROTOCOL); dataset1.setIdentifier("FK2ABCDEF"); - + //Reset to get rid of cached @transient value dataset1.setPidGenerator(null); assertEquals("dc1", dataset1.getGlobalId().getProviderId()); assertEquals("dc1", dataset1.getEffectivePidGenerator().getId()); dataset1.setPidGenerator(null); + //Now set identifier so that the provider has this one in it's managed list (and therefore we can't mint new PIDs in the same auth/shoulder) and therefore we get the effective pid generator dataset1.setIdentifier("FK3ABCDEF"); assertEquals("fake1", dataset1.getGlobalId().getProviderId()); assertEquals("ez1", dataset1.getEffectivePidGenerator().getId()); From 3597c097ec7e871be23dd3472623c2e1bacce2b7 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 9 Jan 2024 12:58:31 -0500 Subject: [PATCH 034/113] update pidprovider discovery to get effective one when necessary --- .../edu/harvard/iq/dataverse/DatasetPage.java | 2 +- .../iq/dataverse/S3PackageImporter.java | 3 +-- .../importer/filesystem/FileRecordWriter.java | 2 +- .../impl/AbstractCreateDatasetCommand.java | 3 ++- .../command/impl/CreateNewDatasetCommand.java | 24 ++++++++++------- .../engine/command/impl/DeletePidCommand.java | 17 +++++++----- .../command/impl/ImportDatasetCommand.java | 4 +-- .../command/impl/RegisterDvObjectCommand.java | 24 +++++++---------- .../command/impl/ReservePidCommand.java | 2 +- .../UpdateDvObjectPIDMetadataCommand.java | 3 ++- .../pidproviders/PidProviderFactoryBean.java | 26 ------------------- 11 files changed, 45 insertions(+), 65 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 2547682a119..0e95f524ec4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -2121,7 +2121,7 @@ private String init(boolean initFull) { //Need to assign an identifier prior to calls to requestDirectUploadUrl if direct upload is used. if ( isEmpty(dataset.getIdentifier()) && systemConfig.directUploadEnabled(dataset) ) { CommandContext ctxt = commandEngine.getContext(); - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(dataset); + PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(dataset); dataset.setIdentifier(pidProvider.generateDatasetIdentifier(dataset)); } dataverseTemplates.addAll(dataverseService.find(ownerId).getTemplates()); diff --git a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java index 4f275daefdc..7c8dda4cb25 100644 --- a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java @@ -204,7 +204,7 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t fmd.setDatasetVersion(dataset.getLatestVersion()); FileUtil.generateS3PackageStorageIdentifier(packageFile); - PidProvider pidProvider = commandEngine.getContext().pidProviderFactory().getPidProvider(dataset); + PidProvider pidProvider = commandEngine.getContext().dvObjects().getEffectivePidGenerator(dataset); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { String packageIdentifier = pidProvider.generateDataFileIdentifier(packageFile); packageFile.setIdentifier(packageIdentifier); @@ -223,7 +223,6 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t if (!packageFile.isIdentifierRegistered()) { String doiRetString = ""; - pidProvider = commandEngine.getContext().pidProviderFactory().getPidProvider(dataset); try { doiRetString = pidProvider.createIdentifier(packageFile); } catch (Throwable e) { diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java index 0588fc76b1c..90fc421f52a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java @@ -360,7 +360,7 @@ private DataFile createPackageDataFile(List files) { if (commandEngine.getContext().systemConfig().isFilePIDsEnabledForCollection(dataset.getOwner())) { - PidProvider pidProvider = commandEngine.getContext().pidProviderFactory().getPidProvider(packageFile); + PidProvider pidProvider = commandEngine.getContext().dvObjects().getEffectivePidGenerator(dataset); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { packageFile.setIdentifier(pidProvider.generateDataFileIdentifier(packageFile)); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index 5e6869df7d8..1f48e069dd3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -13,6 +13,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import static edu.harvard.iq.dataverse.util.StringUtil.isEmpty; import java.io.IOException; @@ -82,7 +83,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { additionalParameterTests(ctxt); Dataset theDataset = getDataset(); - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(theDataset); + PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(theDataset); if ( isEmpty(theDataset.getIdentifier()) ) { theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java index e1ae316fe54..561e3fdc96b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java @@ -3,6 +3,7 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.Dataverse; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.RoleAssignment; import edu.harvard.iq.dataverse.Template; import edu.harvard.iq.dataverse.UserNotification; @@ -13,6 +14,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import static edu.harvard.iq.dataverse.util.StringUtil.nonEmpty; @@ -71,14 +73,18 @@ public CreateNewDatasetCommand(Dataset theDataset, DataverseRequest aRequest, Te */ @Override protected void additionalParameterTests(CommandContext ctxt) throws CommandException { - if ( nonEmpty(getDataset().getIdentifier()) ) { - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(getDataset()); - - if ( !pidProvider.isGlobalIdUnique(getDataset().getGlobalId()) ) { - throw new IllegalCommandException(String.format("Dataset with identifier '%s', protocol '%s' and authority '%s' already exists", - getDataset().getIdentifier(), getDataset().getProtocol(), getDataset().getAuthority()), - this); - } + if (nonEmpty(getDataset().getIdentifier())) { + GlobalId pid = getDataset().getGlobalId(); + if (pid != null) { + PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderId()); + + if (!pidProvider.isGlobalIdUnique(pid)) { + throw new IllegalCommandException(String.format( + "Dataset with identifier '%s', protocol '%s' and authority '%s' already exists", + getDataset().getIdentifier(), getDataset().getProtocol(), getDataset().getAuthority()), + this); + } + } } } @@ -89,7 +95,7 @@ protected DatasetVersion getVersionToPersist( Dataset theDataset ) { @Override protected void handlePid(Dataset theDataset, CommandContext ctxt) throws CommandException { - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(theDataset); + PidProvider pidProvider = PidUtil.getPidProvider(theDataset.getGlobalId().getProviderId()); if(!pidProvider.canManagePID()) { throw new IllegalCommandException("PID Provider " + pidProvider.getProviderInformation().get(0) + " is not configured.", this); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java index b1d7c4a5437..c4910dd10c2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeletePidCommand.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.util.BundleUtil; import org.apache.commons.httpclient.HttpException; @@ -37,24 +38,26 @@ public DeletePidCommand(DataverseRequest request, Dataset dataset) { protected void executeImpl(CommandContext ctxt) throws CommandException { if (!(getUser() instanceof AuthenticatedUser) || !getUser().isSuperuser()) { - throw new PermissionException(BundleUtil.getStringFromBundle("admin.api.auth.mustBeSuperUser"), - this, Collections.singleton(Permission.EditDataset), dataset); + throw new PermissionException(BundleUtil.getStringFromBundle("admin.api.auth.mustBeSuperUser"), this, + Collections.singleton(Permission.EditDataset), dataset); } - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(dataset); - + PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderId()); + try { - pidProvider.deleteIdentifier(dataset); + pidProvider.deleteIdentifier(dataset); // Success! Clear the create time, etc. dataset.setGlobalIdCreateTime(null); dataset.setIdentifierRegistered(false); ctxt.datasets().merge(dataset); } catch (HttpException hex) { - String message = BundleUtil.getStringFromBundle("pids.deletePid.failureExpected", Arrays.asList(dataset.getGlobalId().asString(), Integer.toString(hex.getReasonCode()))); + String message = BundleUtil.getStringFromBundle("pids.deletePid.failureExpected", + Arrays.asList(dataset.getGlobalId().asString(), Integer.toString(hex.getReasonCode()))); logger.info(message); throw new IllegalCommandException(message, this); } catch (Exception ex) { - String message = BundleUtil.getStringFromBundle("pids.deletePid.failureOther", Arrays.asList(dataset.getGlobalId().asString(), ex.getLocalizedMessage())); + String message = BundleUtil.getStringFromBundle("pids.deletePid.failureOther", + Arrays.asList(dataset.getGlobalId().asString(), ex.getLocalizedMessage())); logger.info(message); throw new IllegalCommandException(message, this); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java index 83b78f68f26..772c989264c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportDatasetCommand.java @@ -7,8 +7,8 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandExecutionException; import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; -import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import java.io.IOException; import java.util.Collections; @@ -80,7 +80,7 @@ protected void additionalParameterTests(CommandContext ctxt) throws CommandExcep * Dataverse) but aren't findable to be used. That could be the case if, for * example, someone was importing a draft dataset from elsewhere. */ - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(ds); + PidProvider pidProvider = PidUtil.getPidProvider(ds.getGlobalId().getProviderId()); if (pidProvider != null) { if (pidProvider.alreadyRegistered(ds.getGlobalId(), true)) { return; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java index c481f13d465..d0d45b57a76 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java @@ -4,7 +4,7 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DvObject; -import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.DvObjectContainer; import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand; import edu.harvard.iq.dataverse.engine.command.CommandContext; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; @@ -12,14 +12,9 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import java.sql.Timestamp; import java.util.Date; -import edu.harvard.iq.dataverse.batch.util.LoggingUtil; -import java.io.IOException; -import org.apache.solr.client.solrj.SolrServerException; - /** * * @author skraffmi @@ -49,15 +44,15 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { //Only continue if you can successfully migrate the handle if (!processMigrateHandle(ctxt)) return; } - String nonNullDefaultIfKeyNotFound = ""; - String protocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - String authority = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); + DvObjectContainer container = (target instanceof DvObjectContainer) ? (DvObjectContainer) target : target.getOwner(); // Get the pidProvider that is configured to mint new IDs - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(target); + PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(container); + try { //Test to see if identifier already present //if so, leave. if (target.getIdentifier() == null || target.getIdentifier().isEmpty()) { + if (target.isInstanceofDataset()) { target.setIdentifier(pidProvider.generateDatasetIdentifier((Dataset) target)); @@ -65,12 +60,13 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { target.setIdentifier(pidProvider.generateDataFileIdentifier((DataFile) target)); } if (target.getProtocol() == null) { - target.setProtocol(protocol); + target.setProtocol(pidProvider.getProtocol()); } if (target.getAuthority() == null) { - target.setAuthority(authority); + target.setAuthority(pidProvider.getAuthority()); } } + if (pidProvider.alreadyRegistered(target)) { return; } @@ -98,10 +94,10 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { if (df.getIdentifier() == null || df.getIdentifier().isEmpty()) { df.setIdentifier(pidProvider.generateDataFileIdentifier(df)); if (df.getProtocol() == null || df.getProtocol().isEmpty()) { - df.setProtocol(protocol); + df.setProtocol(pidProvider.getProtocol()); } if (df.getAuthority() == null || df.getAuthority().isEmpty()) { - df.setAuthority(authority); + df.setAuthority(pidProvider.getAuthority()); } } doiRetString = pidProvider.createIdentifier(df); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java index 65324860894..b7e3ddd8ce6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ReservePidCommand.java @@ -42,7 +42,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { this, Collections.singleton(Permission.EditDataset), dataset); } - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(dataset); + PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(dataset); try { String returnString = pidProvider.createIdentifier(dataset); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java index 529aa37a98d..b9dfaee5547 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import java.sql.Timestamp; @@ -46,7 +47,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { //the single dataset update api checks for drafts before calling the command return; } - PidProvider pidProvider = ctxt.pidProviderFactory().getPidProvider(target); + PidProvider pidProvider = PidUtil.getPidProvider(target.getGlobalId().getProviderId()); try { Boolean doiRetString = pidProvider.publicizeIdentifier(target); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index fb8457df6c3..d60d317b79e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -139,32 +139,6 @@ String generateNewIdentifierByStoredProcedure() { return dvObjectService.generateNewIdentifierByStoredProcedure(); } - /** - * A method to get the PidProvider for a given DvObject - intended for use when it is not known whether the object has a PID yet or not. - * If it does, the PidUtil method can be called directly to get the PidProvider. - * @param dvObject - * @return - a PidProvider for the object (may be one of the Unmanaged providers) - */ - @Deprecated - public PidProvider getPidProvider(DvObject dvObject) { - GlobalId pid = dvObject.getGlobalId(); - if (pid != null) { - return PidUtil.getPidProvider(pid.getProviderId()); - } else { - // ToDo - get parent settings rather than global - String nonNullDefaultIfKeyNotFound = ""; - String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol, - nonNullDefaultIfKeyNotFound); - String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority, - nonNullDefaultIfKeyNotFound); - String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder, - nonNullDefaultIfKeyNotFound); - - return PidUtil.getPidProvider(protocol, authority, shoulder); - } - } - - public PidProvider getDefaultPidGenerator() { Optional pidProviderDefaultId = JvmSettings.PID_DEFAULT_PROVIDER.lookupOptional(String.class); if(pidProviderDefaultId.isPresent()) { From 2d095e3d181ae1764138a8cd53e77ad1c257cff3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 9 Jan 2024 17:45:05 -0500 Subject: [PATCH 035/113] replace all refs to global protocol/auth/shoulder settings xcept one keeping the new PidProviderFactoryBean.getDefaultPidGenerator() for now as a possible way to stay ~backward comaptible All the rest - tried to find the appropriate PidProvider to supply the values --- .../edu/harvard/iq/dataverse/DatasetPage.java | 12 ++- .../iq/dataverse/DatasetServiceBean.java | 75 --------------- .../harvard/iq/dataverse/DataversePage.java | 6 ++ .../iq/dataverse/EditDatafilesPage.java | 3 - .../iq/dataverse/S3PackageImporter.java | 8 +- .../harvard/iq/dataverse/SettingsWrapper.java | 24 ----- .../edu/harvard/iq/dataverse/api/Admin.java | 93 ++++++++++--------- .../harvard/iq/dataverse/api/Dataverses.java | 11 +-- .../iq/dataverse/api/MakeDataCountApi.java | 14 ++- .../CollectionDepositManagerImpl.java | 15 +-- .../api/imports/ImportServiceBean.java | 5 +- .../importer/filesystem/FileRecordWriter.java | 7 +- .../impl/AbstractCreateDatasetCommand.java | 5 +- .../FinalizeDatasetPublicationCommand.java | 11 +-- .../command/impl/PublishDatasetCommand.java | 22 +---- .../command/impl/RegisterDvObjectCommand.java | 10 +- .../UpdateDvObjectPIDMetadataCommand.java | 13 ++- .../pidproviders/AbstractPidProvider.java | 14 ++- .../dataverse/pidproviders/PidProvider.java | 7 ++ .../iq/dataverse/pidproviders/PidUtil.java | 5 + .../settings/SettingsServiceBean.java | 10 +- .../iq/dataverse/util/SystemConfig.java | 19 ---- .../iq/dataverse/util/json/JsonParser.java | 4 +- .../workflow/WorkflowServiceBean.java | 18 ++-- src/main/webapp/dataset.xhtml | 2 +- src/main/webapp/dataverse.xhtml | 13 +++ 26 files changed, 171 insertions(+), 255 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 0e95f524ec4..50a1b594a2d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -43,6 +43,8 @@ import edu.harvard.iq.dataverse.ingest.IngestServiceBean; import edu.harvard.iq.dataverse.license.LicenseServiceBean; import edu.harvard.iq.dataverse.metadataimport.ForeignMetadataImportServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; @@ -1925,9 +1927,6 @@ private String init(boolean initFull) { guestbookResponse = new GuestbookResponse(); - String nonNullDefaultIfKeyNotFound = ""; - protocol = settingsWrapper.getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - authority = settingsWrapper.getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); String sortOrder = getSortOrder(); if(sortOrder != null) { FileMetadata.setCategorySortOrder(sortOrder); @@ -2330,7 +2329,8 @@ private void displayLockInfo(Dataset dataset) { // With DataCite, we try to reserve the DOI when the dataset is created. Sometimes this // fails because DataCite is down. We show the message below to set expectations that the // "Publish" button won't work until the DOI has been reserved using the "Reserve PID" API. - if (settingsWrapper.isDataCiteInstallation() && dataset.getGlobalIdCreateTime() == null && editMode != EditMode.CREATE) { + PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderId()); + if (DataCiteDOIProvider.TYPE.equals(pidProvider.getProviderType()) && dataset.getGlobalIdCreateTime() == null && editMode != EditMode.CREATE) { JH.addMessage(FacesMessage.SEVERITY_WARN, BundleUtil.getStringFromBundle("dataset.locked.pidNotReserved.message"), BundleUtil.getStringFromBundle("dataset.locked.pidNotReserved.message.details")); } @@ -6396,5 +6396,9 @@ public String getSignpostingLinkHeader() { } return signpostingLinkHeader; } + + public boolean isDOI() { + return DOIProvider.DOI_PROTOCOL.equals(dataset.getGlobalId().getProtocol()); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java index ac6a46a300a..a32141b8baf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java @@ -939,81 +939,6 @@ public void callFinalizePublishCommandAsynchronously(Long datasetId, CommandCont } } - /* - Experimental asynchronous method for requesting persistent identifiers for - datafiles. We decided not to run this method on upload/create (so files - will not have persistent ids while in draft; when the draft is published, - we will force obtaining persistent ids for all the files in the version. - - If we go back to trying to register global ids on create, care will need to - be taken to make sure the asynchronous changes below are not conflicting with - the changes from file ingest (which may be happening in parallel, also - asynchronously). We would also need to lock the dataset (similarly to how - tabular ingest logs the dataset), to prevent the user from publishing the - version before all the identifiers get assigned - otherwise more conflicts - are likely. (It sounds like it would make sense to treat these two tasks - - persistent identifiers for files and ingest - as one post-upload job, so that - they can be run in sequence). -- L.A. Mar. 2018 - */ - @Asynchronous - @Deprecated - public void obtainPersistentIdentifiersForDatafiles(Dataset dataset) { - PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderId()); - - //If the Id type is sequential and Dependent then write file identifiers outside the command - String datasetIdentifier = dataset.getIdentifier(); - Long maxIdentifier = null; - - if (systemConfig.isDataFilePIDSequentialDependent()) { - maxIdentifier = getMaximumExistingDatafileIdentifier(dataset); - } - - for (DataFile datafile : dataset.getFiles()) { - logger.info("Obtaining persistent id for datafile id=" + datafile.getId()); - - if (datafile.getIdentifier() == null || datafile.getIdentifier().isEmpty()) { - - logger.info("Obtaining persistent id for datafile id=" + datafile.getId()); - - if (maxIdentifier != null) { - maxIdentifier++; - datafile.setIdentifier(datasetIdentifier + "/" + maxIdentifier.toString()); - } else { - datafile.setIdentifier(pidProvider.generateDataFileIdentifier(datafile)); - } - - if (datafile.getProtocol() == null) { - datafile.setProtocol(settingsService.getValueForKey(SettingsServiceBean.Key.Protocol, "")); - } - if (datafile.getAuthority() == null) { - datafile.setAuthority(settingsService.getValueForKey(SettingsServiceBean.Key.Authority, "")); - } - - logger.info("identifier: " + datafile.getIdentifier()); - - String doiRetString; - - try { - logger.log(Level.FINE, "creating identifier"); - doiRetString = pidProvider.createIdentifier(datafile); - } catch (Throwable e) { - logger.log(Level.WARNING, "Exception while creating Identifier: " + e.getMessage(), e); - doiRetString = ""; - } - - // Check return value to make sure registration succeeded - if (!pidProvider.registerWhenPublished() && doiRetString.contains(datafile.getIdentifier())) { - datafile.setIdentifierRegistered(true); - datafile.setGlobalIdCreateTime(new Date()); - } - - DataFile merged = em.merge(datafile); - merged = null; - } - - } - } - public long findStorageSize(Dataset dataset) throws IOException { return findStorageSize(dataset, false, GetDatasetStorageSizeCommand.Mode.STORAGE, null); } diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 943a74327d5..2db31b631fb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -15,6 +15,8 @@ import edu.harvard.iq.dataverse.engine.command.impl.LinkDataverseCommand; import edu.harvard.iq.dataverse.engine.command.impl.PublishDataverseCommand; import edu.harvard.iq.dataverse.engine.command.impl.UpdateDataverseCommand; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.search.FacetCategory; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.search.SearchFields; @@ -1289,4 +1291,8 @@ public String getCurationLabelSetNameLabel() { public Set> getGuestbookEntryOptions() { return settingsWrapper.getGuestbookEntryOptions(this.dataverse).entrySet(); } + + public Set getPidProviderIds() { + return PidUtil.getManagedProviderIds(); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index a6f31e24764..993cb02b66b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -1237,9 +1237,6 @@ public String save() { - We decided not to bother obtaining persistent ids for new files as they are uploaded and created. The identifiers will be assigned later, when the version is published. - - logger.info("starting async job for obtaining persistent ids for files."); - datasetService.obtainPersistentIdentifiersForDatafiles(dataset); */ } diff --git a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java index 7c8dda4cb25..7d97353d6d9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java @@ -210,15 +210,11 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t packageFile.setIdentifier(packageIdentifier); } - String nonNullDefaultIfKeyNotFound = ""; - String protocol = commandEngine.getContext().settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - String authority = commandEngine.getContext().settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); - if (packageFile.getProtocol() == null) { - packageFile.setProtocol(protocol); + packageFile.setProtocol(pidProvider.getProtocol()); } if (packageFile.getAuthority() == null) { - packageFile.setAuthority(authority); + packageFile.setAuthority(pidProvider.getAuthority()); } if (!packageFile.isIdentifierRegistered()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/SettingsWrapper.java b/src/main/java/edu/harvard/iq/dataverse/SettingsWrapper.java index 8ab1e87aef2..964c58b75f6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/SettingsWrapper.java +++ b/src/main/java/edu/harvard/iq/dataverse/SettingsWrapper.java @@ -400,13 +400,6 @@ public boolean isHTTPUpload(){ return httpUpload; } - public boolean isDataFilePIDSequentialDependent(){ - if (dataFilePIDSequentialDependent == null) { - dataFilePIDSequentialDependent = systemConfig.isDataFilePIDSequentialDependent(); - } - return dataFilePIDSequentialDependent; - } - public String getSupportTeamName() { String systemEmail = getValueForKey(SettingsServiceBean.Key.SystemEmail); InternetAddress systemAddress = MailUtil.parseSystemAddress(systemEmail); @@ -470,23 +463,6 @@ public Map getConfiguredLocales() { return configuredLocales; } - public boolean isDoiInstallation() { - String protocol = getValueForKey(SettingsServiceBean.Key.Protocol); - if ("doi".equals(protocol)) { - return true; - } else { - return false; - } - } - - public boolean isDataCiteInstallation() { - String protocol = getValueForKey(SettingsServiceBean.Key.DoiProvider); - if ("DataCite".equals(protocol)) { - return true; - } else { - return false; - } - } public boolean isMakeDataCountDisplayEnabled() { boolean safeDefaultIfKeyNotFound = (getValueForKey(SettingsServiceBean.Key.MDCLogPath)!=null); //Backward compatible diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 5928096304f..207a88f94bb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -14,6 +14,7 @@ import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DataverseSession; import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.api.auth.AuthRequired; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.validation.EMailValidator; @@ -136,46 +137,48 @@ public class Admin extends AbstractApiBean { private static final Logger logger = Logger.getLogger(Admin.class.getName()); - @EJB - AuthenticationProvidersRegistrationServiceBean authProvidersRegistrationSvc; - @EJB - BuiltinUserServiceBean builtinUserService; - @EJB - ShibServiceBean shibService; - @EJB - AuthTestDataServiceBean authTestDataService; - @EJB - UserServiceBean userService; - @EJB - IngestServiceBean ingestService; - @EJB - DataFileServiceBean fileService; - @EJB - DatasetServiceBean datasetService; - @EJB - DataverseServiceBean dataverseService; - @EJB - DatasetVersionServiceBean datasetversionService; - @Inject - DataverseRequestServiceBean dvRequestService; - @EJB - EjbDataverseEngine commandEngine; - @EJB - GroupServiceBean groupService; - @EJB - SettingsServiceBean settingsService; - @EJB - DatasetVersionServiceBean datasetVersionService; - @EJB - ExplicitGroupServiceBean explicitGroupService; - @EJB - BannerMessageServiceBean bannerMessageService; - @EJB - TemplateServiceBean templateService; - - // Make the session available - @Inject - DataverseSession session; + @EJB + AuthenticationProvidersRegistrationServiceBean authProvidersRegistrationSvc; + @EJB + BuiltinUserServiceBean builtinUserService; + @EJB + ShibServiceBean shibService; + @EJB + AuthTestDataServiceBean authTestDataService; + @EJB + UserServiceBean userService; + @EJB + IngestServiceBean ingestService; + @EJB + DataFileServiceBean fileService; + @EJB + DatasetServiceBean datasetService; + @EJB + DataverseServiceBean dataverseService; + @EJB + DvObjectServiceBean dvObjectService; + @EJB + DatasetVersionServiceBean datasetversionService; + @Inject + DataverseRequestServiceBean dvRequestService; + @EJB + EjbDataverseEngine commandEngine; + @EJB + GroupServiceBean groupService; + @EJB + SettingsServiceBean settingsService; + @EJB + DatasetVersionServiceBean datasetVersionService; + @EJB + ExplicitGroupServiceBean explicitGroupService; + @EJB + BannerMessageServiceBean bannerMessageService; + @EJB + TemplateServiceBean templateService; + + // Make the session available + @Inject + DataverseSession session; public static final String listUsersPartialAPIPath = "list-users"; public static final String listUsersFullAPIPath = "/api/admin/" + listUsersPartialAPIPath; @@ -1474,10 +1477,7 @@ public Response isOrcidEnabled() { public Response reregisterHdlToPID(@Context ContainerRequestContext crc, @PathParam("id") String id) { logger.info("Starting to reregister " + id + " Dataset Id. (from hdl to doi)" + new Date()); try { - if (settingsSvc.get(SettingsServiceBean.Key.Protocol.toString()).equals(HandlePidProvider.HDL_PROTOCOL)) { - logger.info("Bad Request protocol set to handle " ); - return error(Status.BAD_REQUEST, BundleUtil.getStringFromBundle("admin.api.migrateHDL.failure.must.be.set.for.doi")); - } + User u = getRequestUser(crc); if (!u.isSuperuser()) { @@ -1487,6 +1487,11 @@ public Response reregisterHdlToPID(@Context ContainerRequestContext crc, @PathPa DataverseRequest r = createDataverseRequest(u); Dataset ds = findDatasetOrDie(id); + + if (HandlePidProvider.HDL_PROTOCOL.equals(dvObjectService.getEffectivePidGenerator(ds).getProtocol())) { + logger.info("Bad Request protocol set to handle " ); + return error(Status.BAD_REQUEST, BundleUtil.getStringFromBundle("admin.api.migrateHDL.failure.must.be.set.for.doi")); + } if (ds.getIdentifier() != null && !ds.getIdentifier().isEmpty() && ds.getProtocol().equals(HandlePidProvider.HDL_PROTOCOL)) { execCommand(new RegisterDvObjectCommand(r, ds, true)); } else { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java index 91738a127bf..e44c27487b8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java @@ -74,6 +74,7 @@ import edu.harvard.iq.dataverse.engine.command.impl.UpdateMetadataBlockFacetsCommand; import edu.harvard.iq.dataverse.engine.command.impl.ValidateDatasetJsonCommand; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; @@ -559,12 +560,10 @@ public Response recreateDataset(@Context ContainerRequestContext crc, String jso ds.setOwner(owner); ds = JSONLDUtil.updateDatasetMDFromJsonLD(ds, jsonLDBody, metadataBlockSvc, datasetFieldSvc, false, true, licenseSvc); //ToDo - verify PID is one Dataverse can manage (protocol/authority/shoulder match) - if(! - (ds.getAuthority().equals(settingsService.getValueForKey(SettingsServiceBean.Key.Authority))&& - ds.getProtocol().equals(settingsService.getValueForKey(SettingsServiceBean.Key.Protocol))&& - ds.getIdentifier().startsWith(settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder)))) { - throw new BadRequestException("Cannot recreate a dataset that has a PID that doesn't match the server's settings"); - } + if (!PidUtil.getPidProvider(ds.getGlobalId().getProviderId()).canManagePID()) { + throw new BadRequestException( + "Cannot recreate a dataset that has a PID that doesn't match the server's settings"); + } if(!dvObjectSvc.isGlobalIdLocallyUnique(ds.getGlobalId())) { throw new BadRequestException("Cannot recreate a dataset whose PID is already in use"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java b/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java index b2696757220..8d80b568da0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java @@ -2,10 +2,14 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetServiceBean; +import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitations; import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitationsServiceBean; import edu.harvard.iq.dataverse.makedatacount.DatasetMetrics; import edu.harvard.iq.dataverse.makedatacount.DatasetMetricsServiceBean; +import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; import edu.harvard.iq.dataverse.util.json.JsonUtil; @@ -131,8 +135,14 @@ public Response addUsageMetricsFromSushiReportAll(@PathParam("id") String id, @Q public Response updateCitationsForDataset(@PathParam("id") String id) throws IOException { try { Dataset dataset = findDatasetOrDie(id); - String persistentId = dataset.getGlobalId().toString(); - //ToDo - if this isn't a DOI? + GlobalId pid = dataset.getGlobalId(); + PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderId()); + // Only supported for DOIs and for DataCite DOI providers + if(!DataCiteDOIProvider.TYPE.equals(pidProvider.getProviderType())) { + return error(Status.BAD_REQUEST, "Only DataCite DOI providers are supported"); + } + String persistentId = pid.toString(); + // DataCite wants "doi=", not "doi:". String authorityPlusIdentifier = persistentId.replaceFirst("doi:", ""); // Request max page size and then loop to handle multiple pages diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/CollectionDepositManagerImpl.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/CollectionDepositManagerImpl.java index 5bc50903be8..a81848bd7af 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/CollectionDepositManagerImpl.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/CollectionDepositManagerImpl.java @@ -6,6 +6,7 @@ import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.EjbDataverseEngine; import edu.harvard.iq.dataverse.PermissionServiceBean; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; @@ -14,6 +15,7 @@ import edu.harvard.iq.dataverse.api.imports.ImportGenericServiceBean; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.impl.CreateNewDatasetCommand; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.ConstraintViolationUtil; import java.util.logging.Level; @@ -44,6 +46,8 @@ public class CollectionDepositManagerImpl implements CollectionDepositManager { @EJB DatasetServiceBean datasetService; @EJB + DvObjectServiceBean dvObjectService; + @EJB PermissionServiceBean permissionService; @Inject SwordAuth swordAuth; @@ -96,13 +100,10 @@ public DepositReceipt createNew(String collectionUri, Deposit deposit, AuthCrede Dataset dataset = new Dataset(); dataset.setOwner(dvThatWillOwnDataset); - String nonNullDefaultIfKeyNotFound = ""; - String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); - - dataset.setProtocol(protocol); - dataset.setAuthority(authority); - //Wait until the create command before actually getting an identifier + PidProvider pidProvider = dvObjectService.getEffectivePidGenerator(dataset); + dataset.setProtocol(pidProvider.getProtocol()); + dataset.setAuthority(pidProvider.getAuthority()); + //Wait until the create command before actually getting an identifier logger.log(Level.FINE, "DS Deposit identifier: {0}", dataset.getIdentifier()); AbstractCreateDatasetCommand createDatasetCommand = new CreateNewDatasetCommand(dataset, dvReq); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java index c17ba909230..39977190691 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java @@ -38,6 +38,8 @@ import edu.harvard.iq.dataverse.util.json.JsonParser; import edu.harvard.iq.dataverse.util.json.JsonUtil; import edu.harvard.iq.dataverse.license.LicenseServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -421,8 +423,9 @@ public JsonObjectBuilder doImport(DataverseRequest dataverseRequest, Dataverse o // For ImportType.NEW, if the user supplies a global identifier, and it's not a protocol // we support, it will be rejected. + if (importType.equals(ImportType.NEW)) { - if (ds.getGlobalId().asString() != null && !ds.getProtocol().equals(settingsService.getValueForKey(SettingsServiceBean.Key.Protocol, ""))) { + if (ds.getGlobalId().asString() != null && !PidUtil.getPidProvider(ds.getGlobalId().getProviderId()).canManagePID()) { throw new ImportException("Could not register id " + ds.getGlobalId().asString() + ", protocol not supported"); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java index 90fc421f52a..6899856683d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java @@ -364,14 +364,11 @@ private DataFile createPackageDataFile(List files) { if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { packageFile.setIdentifier(pidProvider.generateDataFileIdentifier(packageFile)); } - String nonNullDefaultIfKeyNotFound = ""; - String protocol = commandEngine.getContext().settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound); - String authority = commandEngine.getContext().settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound); if (packageFile.getProtocol() == null) { - packageFile.setProtocol(protocol); + packageFile.setProtocol(pidProvider.getProtocol()); } if (packageFile.getAuthority() == null) { - packageFile.setAuthority(authority); + packageFile.setAuthority(pidProvider.getAuthority()); } if (!packageFile.isIdentifierRegistered()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index 1f48e069dd3..b9f7c75ce78 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -108,12 +108,11 @@ public Dataset execute(CommandContext ctxt) throws CommandException { dataFile.setCreateDate(theDataset.getCreateDate()); } - String nonNullDefaultIfKeyNotFound = ""; if (theDataset.getProtocol()==null) { - theDataset.setProtocol(ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, nonNullDefaultIfKeyNotFound)); + theDataset.setProtocol(pidProvider.getProtocol()); } if (theDataset.getAuthority()==null) { - theDataset.setAuthority(ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound)); + theDataset.setAuthority(pidProvider.getAuthority()); } if (theDataset.getStorageIdentifier() == null) { String driverId = theDataset.getEffectiveStorageDriverId(); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java index d6d5a20db27..eea66d8b38a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java @@ -393,9 +393,6 @@ private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) t if (pidProvider != null) { try { - String currentGlobalIdProtocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, ""); - String currentGlobalAuthority = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, ""); - String dataFilePIDFormat = ctxt.settings().getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, "DEPENDENT"); boolean isFilePIDsEnabled = ctxt.systemConfig().isFilePIDsEnabledForCollection(getDataset().getOwner()); // We will skip trying to register the global identifiers for datafiles // if "dependent" file-level identifiers are requested, AND the naming @@ -406,9 +403,11 @@ private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) t // an authority that's different from what's currently configured. // Additionaly in 4.9.3 we have added a system variable to disable // registering file PIDs on the installation level. - //ToDo - update to handle multiple PidProviders - if (((currentGlobalIdProtocol.equals(protocol) && currentGlobalAuthority.equals(authority)) - || dataFilePIDFormat.equals("INDEPENDENT")) + boolean registerGlobalIdsForFiles = + ctxt.systemConfig().isFilePIDsEnabledForCollection(getDataset().getOwner()) && + ctxt.dvObjects().getEffectivePidGenerator(dataset).canCreatePidsLike(dataset.getGlobalId()); + + if (registerGlobalIdsForFiles && isFilePIDsEnabled && dataset.getLatestVersion().getMinorVersionNumber() != null && dataset.getLatestVersion().getMinorVersionNumber().equals((long) 0)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java index 18c7d05cf1b..6b95f3b6de1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java @@ -130,24 +130,15 @@ public PublishDatasetResult execute(CommandContext ctxt) throws CommandException // ... // Additionaly in 4.9.3 we have added a system variable to disable // registering file PIDs on the installation level. - String currentGlobalIdProtocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, ""); - String currentGlobalAuthority= ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, ""); - String dataFilePIDFormat = ctxt.settings().getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, "DEPENDENT"); boolean registerGlobalIdsForFiles = - (currentGlobalIdProtocol.equals(theDataset.getProtocol()) || dataFilePIDFormat.equals("INDEPENDENT")) - && ctxt.systemConfig().isFilePIDsEnabledForCollection(theDataset.getOwner()); - - if ( registerGlobalIdsForFiles ){ - registerGlobalIdsForFiles = currentGlobalAuthority.equals( theDataset.getAuthority() ); - } + ctxt.systemConfig().isFilePIDsEnabledForCollection(getDataset().getOwner()) && + ctxt.dvObjects().getEffectivePidGenerator(getDataset()).canCreatePidsLike(getDataset().getGlobalId()); boolean validatePhysicalFiles = ctxt.systemConfig().isDatafileValidationOnPublishEnabled(); // As of v5.0, publishing a dataset is always done asynchronously, // with the dataset locked for the duration of the operation. - //if ((registerGlobalIdsForFiles || validatePhysicalFiles) - // && theDataset.getFiles().size() > ctxt.systemConfig().getPIDAsynchRegFileCount()) { String info = "Publishing the dataset; "; info += registerGlobalIdsForFiles ? "Registering PIDs for Datafiles; " : ""; @@ -178,15 +169,6 @@ public PublishDatasetResult execute(CommandContext ctxt) throws CommandException // method: //ctxt.datasets().callFinalizePublishCommandAsynchronously(theDataset.getId(), ctxt, request, datasetExternallyReleased); return new PublishDatasetResult(theDataset, Status.Inprogress); - - /** - * Code for for "synchronous" (while-you-wait) publishing - * is preserved below, commented out: - } else { - // Synchronous publishing (no workflow involved) - theDataset = ctxt.engine().submit(new FinalizeDatasetPublicationCommand(theDataset, getRequest(),datasetExternallyReleased)); - return new PublishDatasetResult(theDataset, Status.Completed); - } */ } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java index d0d45b57a76..d27a26da917 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java @@ -40,14 +40,14 @@ public RegisterDvObjectCommand(DataverseRequest aRequest, DvObject target, Boole @Override protected void executeImpl(CommandContext ctxt) throws CommandException { - if(this.migrateHandle){ - //Only continue if you can successfully migrate the handle - if (!processMigrateHandle(ctxt)) return; - } DvObjectContainer container = (target instanceof DvObjectContainer) ? (DvObjectContainer) target : target.getOwner(); // Get the pidProvider that is configured to mint new IDs PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(container); - + if(this.migrateHandle){ + //Only continue if you can successfully migrate the handle + if (HandlePidProvider.HDL_PROTOCOL.equals(pidProvider.getProtocol()) || !processMigrateHandle(ctxt)) return; + } + try { //Test to see if identifier already present //if so, leave. diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java index b9dfaee5547..0c463cddec1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDvObjectPIDMetadataCommand.java @@ -57,20 +57,19 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { ctxt.em().flush(); // When updating, we want to traverse through files even if the dataset itself // didn't need updating. - String currentGlobalIdProtocol = ctxt.settings().getValueForKey(SettingsServiceBean.Key.Protocol, ""); - String dataFilePIDFormat = ctxt.settings().getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, "DEPENDENT"); boolean isFilePIDsEnabled = ctxt.systemConfig().isFilePIDsEnabledForCollection(target.getOwner()); // We will skip trying to update the global identifiers for datafiles if they // aren't being used. // If they are, we need to assure that there's an existing PID or, as when - // creating PIDs, that the protocol matches that of the dataset DOI if - // we're going to create a DEPENDENT file PID. - String protocol = target.getProtocol(); + // creating PIDs, that it's possible. + + boolean canCreatePidsForFiles = + isFilePIDsEnabled && ctxt.dvObjects().getEffectivePidGenerator(target).canCreatePidsLike(target.getGlobalId()); + for (DataFile df : target.getFiles()) { if (isFilePIDsEnabled && // using file PIDs and (!(df.getIdentifier() == null || df.getIdentifier().isEmpty()) || // identifier exists, or - currentGlobalIdProtocol.equals(protocol) || // right protocol to create dependent DOIs, or - dataFilePIDFormat.equals("INDEPENDENT"))// or independent. TODO(pm) - check authority too + canCreatePidsForFiles) // we can create PIDs for files ) { doiRetString = pidProvider.publicizeIdentifier(df); if (doiRetString) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 8e2b966d9d0..d64bd1dd05b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -795,7 +795,19 @@ public String getLabel() { } @Override + /** + * True if this provider can manage PIDs in general, this pid is not in the + * managedSet (meaning it is managed but the provider does not generally manage + * it's protocol/authority/separator/shoulder) and either this provider is the + * same as the pid's or we're allowed to create INDEPENDENT pids. The latter + * clause covers the potential case where the effective pid provider/generator + * for the dataset is set to a different one that handles the dataset's pid + * itself. In this case, we can create file PIDs if they are independent. + * @param pid - the related pid to check + * @return true if this provider can manage PIDs like the one supplied + */ public boolean canCreatePidsLike(GlobalId pid) { - return canManagePID() && !managedSet.contains(pid.asString()); + return canManagePID() && !managedSet.contains(pid.asString()) + && (getIdentifierGenerationStyle().equals("INDEPENDENT") || getId().equals(pid.getProviderId())); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index a8368ea2a56..d73f39257c3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -179,6 +179,13 @@ static boolean checkDOIAuthority(String doiAuthority){ Set getExcludedSet(); + /** + * Whether related pids can be created by this pid provider + * @see edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider#canCreatePidsLike(GlobalId) more details in the abstract implementation + * + * @param pid + * @return - whether related pids can be created by this pid provider. + */ boolean canCreatePidsLike(GlobalId pid); } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 4d26202e1f1..9f283c16dda 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.Logger; import jakarta.json.Json; @@ -271,4 +272,8 @@ public static PidProvider getPidProvider(String protocol, String authority, Stri } return null; } + + public static Set getManagedProviderIds() { + return providerMap.keySet(); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 627cef08d8b..047fdfc3202 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -194,7 +194,7 @@ public enum Key { /** authority for global id */ Authority, /** DoiProvider for global id */ - DoiProvider, + //DoiProvider, /** Shoulder for global id - used to create a common prefix on identifiers */ Shoulder, /* Removed for now - tried to add here but DOI Service Bean didn't like it at start-up @@ -351,14 +351,14 @@ Whether Harvesting (OAI) service is enabled 'DEPENEDENT' means the DOI will be the Dataset DOI plus a file DOI with a slash in between. 'INDEPENDENT' means a new global id, completely independent from the dataset-level global id. */ - DataFilePIDFormat, + //DataFilePIDFormat, /* Json array of supported languages */ Languages, /* Number for the minimum number of files to send PID registration to asynchronous workflow */ - PIDAsynchRegFileCount, + //PIDAsynchRegFileCount, /** * */ @@ -367,12 +367,12 @@ Whether Harvesting (OAI) service is enabled /** * Indicates if the Handle service is setup to work 'independently' (No communication with the Global Handle Registry) */ - IndependentHandleService, + //IndependentHandleService, /** Handle to use for authentication if the default is not being used */ - HandleAuthHandle, + //HandleAuthHandle, /** * Archiving can be configured by providing an Archiver class name (class must extend AstractSubmitToArchiverCommand) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java index d8736f5ea0a..9de74c04b8b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java @@ -966,25 +966,6 @@ public Integer getUploadMethodCount(){ return Arrays.asList(uploadMethods.toLowerCase().split("\\s*,\\s*")).size(); } } - public boolean isDataFilePIDSequentialDependent(){ - String doiIdentifierType = settingsService.getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "randomString"); - String doiDataFileFormat = settingsService.getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, "DEPENDENT"); - if (doiIdentifierType.equals("storedProcGenerated") && doiDataFileFormat.equals("DEPENDENT")){ - return true; - } - return false; - } - - public int getPIDAsynchRegFileCount() { - String fileCount = settingsService.getValueForKey(SettingsServiceBean.Key.PIDAsynchRegFileCount, "10"); - int retVal = 10; - try { - retVal = Integer.parseInt(fileCount); - } catch (NumberFormatException e) { - //if no number in the setting we'll return 10 - } - return retVal; - } public boolean isAllowCustomTerms() { boolean safeDefaultIfKeyNotFound = true; diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java index 984c607aac7..2141fcc5fca 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java @@ -318,8 +318,8 @@ public DatasetVersion parseDatasetVersion(JsonObject obj) throws JsonParseExcept public Dataset parseDataset(JsonObject obj) throws JsonParseException { Dataset dataset = new Dataset(); - dataset.setAuthority(obj.getString("authority", null) == null ? settingsService.getValueForKey(SettingsServiceBean.Key.Authority) : obj.getString("authority")); - dataset.setProtocol(obj.getString("protocol", null) == null ? settingsService.getValueForKey(SettingsServiceBean.Key.Protocol) : obj.getString("protocol")); + dataset.setAuthority(obj.getString("authority", null)); + dataset.setProtocol(obj.getString("protocol", null)); dataset.setIdentifier(obj.getString("identifier",null)); String mdl = obj.getString("metadataLanguage",null); if(mdl==null || settingsService.getBaseMetadataLanguageMap(new HashMap(), true).containsKey(mdl)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/workflow/WorkflowServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/workflow/WorkflowServiceBean.java index 47f24c9b8bd..757d447b60a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/workflow/WorkflowServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/workflow/WorkflowServiceBean.java @@ -1,8 +1,10 @@ package edu.harvard.iq.dataverse.workflow; +import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetLock; import edu.harvard.iq.dataverse.DatasetServiceBean; import edu.harvard.iq.dataverse.DataverseRequestServiceBean; +import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.EjbDataverseEngine; import edu.harvard.iq.dataverse.RoleAssigneeServiceBean; import edu.harvard.iq.dataverse.UserNotification; @@ -58,6 +60,9 @@ public class WorkflowServiceBean { @EJB DatasetServiceBean datasets; + + @EJB + DvObjectServiceBean dvObjects; @EJB SettingsServiceBean settings; @@ -387,16 +392,11 @@ private void workflowCompleted(Workflow wf, WorkflowContext ctxt) { //Now lock for FinalizePublication - this block mirrors that in PublishDatasetCommand AuthenticatedUser user = ctxt.getRequest().getAuthenticatedUser(); DatasetLock lock = new DatasetLock(DatasetLock.Reason.finalizePublication, user); - lock.setDataset(ctxt.getDataset()); - String currentGlobalIdProtocol = settings.getValueForKey(SettingsServiceBean.Key.Protocol, ""); - String currentGlobalAuthority= settings.getValueForKey(SettingsServiceBean.Key.Authority, ""); - String dataFilePIDFormat = settings.getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, "DEPENDENT"); + Dataset dataset = ctxt.getDataset(); + lock.setDataset(dataset); boolean registerGlobalIdsForFiles = - (currentGlobalIdProtocol.equals(ctxt.getDataset().getProtocol()) || dataFilePIDFormat.equals("INDEPENDENT")) - && systemConfig.isFilePIDsEnabledForCollection(ctxt.getDataset().getOwner()); - if ( registerGlobalIdsForFiles ){ - registerGlobalIdsForFiles = currentGlobalAuthority.equals( ctxt.getDataset().getAuthority() ); - } + systemConfig.isFilePIDsEnabledForCollection(ctxt.getDataset().getOwner()) && + dvObjects.getEffectivePidGenerator(dataset).canCreatePidsLike(dataset.getGlobalId()); boolean validatePhysicalFiles = systemConfig.isDatafileValidationOnPublishEnabled(); String info = "Publishing the dataset; "; diff --git a/src/main/webapp/dataset.xhtml b/src/main/webapp/dataset.xhtml index e50e68ec162..0adeb7ae4bb 100644 --- a/src/main/webapp/dataset.xhtml +++ b/src/main/webapp/dataset.xhtml @@ -585,7 +585,7 @@ -
+
diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index 41e2807c4fd..9cd7acdab17 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -283,6 +283,19 @@
+
+ + #{bundle.guestbookEntryOption} + + +
+ + + + +
+
From 836538251e23fb7e36f56c01fa79890e1043f00a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 10 Jan 2024 12:12:26 -0500 Subject: [PATCH 036/113] first UI for setting Pid generator --- .../harvard/iq/dataverse/DataversePage.java | 31 ++++++++++++++++--- .../iq/dataverse/DvObjectContainer.java | 17 +++++++--- src/main/java/propertyFiles/Bundle.properties | 2 ++ src/main/webapp/dataverse.xhtml | 14 ++++----- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 2db31b631fb..9e84945e5d5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -16,6 +16,7 @@ import edu.harvard.iq.dataverse.engine.command.impl.PublishDataverseCommand; import edu.harvard.iq.dataverse.engine.command.impl.UpdateDataverseCommand; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.search.FacetCategory; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -36,9 +37,12 @@ import jakarta.faces.view.ViewScoped; import jakarta.inject.Inject; import jakarta.inject.Named; + +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -111,7 +115,9 @@ public enum LinkMode { @EJB DataverseLinkingServiceBean linkingService; @Inject PermissionsWrapper permissionsWrapper; - @Inject DataverseHeaderFragment dataverseHeaderFragment; + @Inject DataverseHeaderFragment dataverseHeaderFragment; + @EJB + PidProviderFactoryBean pidProviderFactoryBean; private Dataverse dataverse = new Dataverse(); @@ -1291,8 +1297,25 @@ public String getCurationLabelSetNameLabel() { public Set> getGuestbookEntryOptions() { return settingsWrapper.getGuestbookEntryOptions(this.dataverse).entrySet(); } - - public Set getPidProviderIds() { - return PidUtil.getManagedProviderIds(); + + public Set> getPidProviderOptions() { + PidProvider defaultPidProvider = pidProviderFactoryBean.getDefaultPidGenerator(); + Set providerIds = PidUtil.getManagedProviderIds(); + Set> options = new HashSet>(); + if (providerIds.size() > 1) { + String label = defaultPidProvider.getLabel() + BundleUtil.getStringFromBundle("dataverse.default") + ": " + + defaultPidProvider.getProtocol() + ":" + defaultPidProvider.getAuthority() + + defaultPidProvider.getSeparator() + defaultPidProvider.getShoulder(); + Entry option = new AbstractMap.SimpleEntry("default", label); + options.add(option); + } + for (String providerId : providerIds) { + PidProvider pidProvider = PidUtil.getPidProvider(providerId); + String label = pidProvider.getLabel() + ": " + pidProvider.getProtocol() + ":" + pidProvider.getAuthority() + + pidProvider.getSeparator() + pidProvider.getShoulder(); + Entry option = new AbstractMap.SimpleEntry(providerId, label); + options.add(option); + } + return options; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java index 6c03fd1eac9..34ffa03cfa2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java @@ -202,14 +202,22 @@ public void setPidGeneratorSpecs(String pidGeneratorSpecs) { this.pidGeneratorSpecs = pidGeneratorSpecs; } - public PidProvider getPidGenerator() { - return pidGenerator; + //Used in JSF when selecting the PidGenerator + public String getPidGeneratorId() { + return getEffectivePidGenerator().getId(); + } + + //Used in JSF when setting the PidGenerator + public void setPidGeneratorId(String pidGeneratorId) { + // Note that the "default" provider will not be found so will result in + // setPidGenerator(null), which unsets the pidGenerator/Specs as desired + setPidGenerator(PidUtil.getPidProvider(pidGeneratorId)); } public void setPidGenerator(PidProvider pidGenerator) { this.pidGenerator = pidGenerator; - JsonObjectBuilder job = jakarta.json.Json.createObjectBuilder(); if (pidGenerator != null) { + JsonObjectBuilder job = jakarta.json.Json.createObjectBuilder(); this.pidGeneratorSpecs = job.add("protocol", pidGenerator.getProtocol()) .add("authority", pidGenerator.getAuthority()).add("shoulder", pidGenerator.getShoulder()) .add("separator", pidGenerator.getSeparator()).build().toString(); @@ -219,7 +227,6 @@ public void setPidGenerator(PidProvider pidGenerator) { } public PidProvider getEffectivePidGenerator() { - PidProvider pidGenerator = getPidGenerator(); if (pidGenerator == null) { String specs = getPidGeneratorSpecs(); if (StringUtils.isBlank(specs)) { @@ -242,8 +249,8 @@ public PidProvider getEffectivePidGenerator() { providerSpecs.getString("authority"), providerSpecs.getString("shoulder")); } } + setPidGenerator(pidGenerator); } - setPidGenerator(pidGenerator); return pidGenerator; } diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 10576c0c116..a289803e968 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -56,6 +56,7 @@ storage=Storage curationLabels=Curation Labels metadataLanguage=Dataset Metadata Language guestbookEntryOption=Guestbook Entry Option +pidProviderOption=PID Provider Option createDataverse=Create Dataverse remove=Remove done=Done @@ -829,6 +830,7 @@ dataverse.curationLabels.disabled=Disabled dataverse.category=Category dataverse.category.title=The type that most closely reflects this dataverse. dataverse.guestbookentryatrequest.title=Whether Guestbooks are displayed to users when they request file access or when they download files. +dataverse.pidProvider.title=The source of PIDs (DOIs, Handles, etc.) when a new PID is created. dataverse.type.selectTab.top=Select one... dataverse.type.selectTab.researchers=Researcher dataverse.type.selectTab.researchProjects=Research Project diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index 9cd7acdab17..5d05cb50285 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -283,17 +283,17 @@ -
- - #{bundle.guestbookEntryOption} +
+ + #{bundle.pidProviderOption} + data-toggle="tooltip" data-placement="auto right" data-original-title="#{bundle['dataverse.pidProvider.title']}">
- - + + - +
From 7a3e1a2dea03397a2ca69b4fbf1865857aec3185 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 10 Jan 2024 15:25:48 -0500 Subject: [PATCH 037/113] typo --- src/main/webapp/dataset.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataset.xhtml b/src/main/webapp/dataset.xhtml index 0adeb7ae4bb..0dad6d250a2 100644 --- a/src/main/webapp/dataset.xhtml +++ b/src/main/webapp/dataset.xhtml @@ -585,7 +585,7 @@ -
+
From 2ee2ead09a8ce649b9e985d070cfa1a706d187b9 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 10 Jan 2024 15:26:07 -0500 Subject: [PATCH 038/113] flyway script to add pid spec column --- .../db/migration/V6.0.0.20__3623-multiple-pid-providers.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/resources/db/migration/V6.0.0.20__3623-multiple-pid-providers.sql diff --git a/src/main/resources/db/migration/V6.0.0.20__3623-multiple-pid-providers.sql b/src/main/resources/db/migration/V6.0.0.20__3623-multiple-pid-providers.sql new file mode 100644 index 00000000000..1d11e178abf --- /dev/null +++ b/src/main/resources/db/migration/V6.0.0.20__3623-multiple-pid-providers.sql @@ -0,0 +1,2 @@ +ALTER TABLE dataverse ADD COLUMN IF NOT EXISTS pidgeneratorspecs TEXT; +ALTER TABLE dataset ADD COLUMN IF NOT EXISTS pidgeneratorspecs TEXT; From 1f0cb94eeb211a2096b3d0dad0bc9f0f75a966a6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 13:58:03 -0500 Subject: [PATCH 039/113] @AutoService and public class for loader discovery --- .../iq/dataverse/pidproviders/DataCiteProviderFactory.java | 5 ++++- .../iq/dataverse/pidproviders/EZIdProviderFactory.java | 5 ++++- .../iq/dataverse/pidproviders/FakeProviderFactory.java | 7 +++++-- .../iq/dataverse/pidproviders/HandleProviderFactory.java | 7 +++++-- .../dataverse/pidproviders/PermaLinkProviderFactory.java | 7 +++++-- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index 1dbf2a87aa2..a78b7aa8e4c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -1,9 +1,12 @@ package edu.harvard.iq.dataverse.pidproviders; +import com.google.auto.service.AutoService; + import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; -class DataCiteProviderFactory implements PidProviderFactory { +@AutoService(PidProviderFactory.class) +public class DataCiteProviderFactory implements PidProviderFactory { @Override public PidProvider createPidProvider(String providerId) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java index d8f3614cd8d..bb4ab1392e7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java @@ -1,9 +1,12 @@ package edu.harvard.iq.dataverse.pidproviders; +import com.google.auto.service.AutoService; + import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; -class EZIdProviderFactory implements PidProviderFactory { +@AutoService(PidProviderFactory.class) +public class EZIdProviderFactory implements PidProviderFactory { @Override public PidProvider createPidProvider(String providerId) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java index 6304874243b..95d512aca48 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java @@ -1,10 +1,13 @@ package edu.harvard.iq.dataverse.pidproviders; +import com.google.auto.service.AutoService; + import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; -class FakeProviderFactory implements PidProviderFactory { - +@AutoService(PidProviderFactory.class) +public class FakeProviderFactory implements PidProviderFactory { + @Override public PidProvider createPidProvider(String providerId) { String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java index 7108c2c631a..be3c7a94c37 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java @@ -1,10 +1,13 @@ package edu.harvard.iq.dataverse.pidproviders; +import com.google.auto.service.AutoService; + import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; -class HandleProviderFactory implements PidProviderFactory { - +@AutoService(PidProviderFactory.class) +public class HandleProviderFactory implements PidProviderFactory { + @Override public PidProvider createPidProvider(String providerId) { String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java index d04ae50c452..13b4de540cb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java @@ -1,10 +1,13 @@ package edu.harvard.iq.dataverse.pidproviders; +import com.google.auto.service.AutoService; + import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; -class PermaLinkProviderFactory implements PidProviderFactory { - +@AutoService(PidProviderFactory.class) +public class PermaLinkProviderFactory implements PidProviderFactory { + @Override public PidProvider createPidProvider(String providerId) { String providerType = JvmSettings.PID_PROVIDER_TYPE.lookup(providerId); From 8d0e2d3fc22e2195437f0c7c29c7f65da96ec95f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 14:01:53 -0500 Subject: [PATCH 040/113] minor cleanup/refactor --- .../java/edu/harvard/iq/dataverse/DvObjectContainer.java | 2 -- .../java/edu/harvard/iq/dataverse/DvObjectServiceBean.java | 4 ++-- .../engine/command/impl/CreateNewDatasetCommand.java | 2 +- .../iq/dataverse/pidproviders/DataCiteDOIProvider.java | 4 ++-- .../harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java | 2 +- .../iq/dataverse/pidproviders/HandlePidProvider.java | 2 +- .../iq/dataverse/pidproviders/PermaLinkPidProvider.java | 6 +++--- .../edu/harvard/iq/dataverse/pidproviders/PidProvider.java | 2 +- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 2 ++ .../java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java index 34ffa03cfa2..9fe1aef9423 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java @@ -11,8 +11,6 @@ import jakarta.json.JsonObjectBuilder; import jakarta.persistence.CascadeType; import java.util.Optional; -import java.util.logging.Logger; - import jakarta.persistence.MappedSuperclass; import jakarta.persistence.OneToOne; import jakarta.persistence.Transient; diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java index 0ba887196f8..b37088afbc8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java @@ -403,8 +403,8 @@ public String generateNewIdentifierByStoredProcedure() { */ public PidProvider getEffectivePidGenerator(DvObjectContainer dvObjectContainer) { PidProvider pidGenerator = dvObjectContainer.getEffectivePidGenerator(); - if(pidGenerator == null) { - pidGenerator = pidProviderFactoryBean.getDefaultPidGenerator(); + if (pidGenerator == null) { + pidGenerator = pidProviderFactoryBean.getDefaultPidGenerator(); } return pidGenerator; } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java index 561e3fdc96b..c22a2cdb4a2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java @@ -97,7 +97,7 @@ protected DatasetVersion getVersionToPersist( Dataset theDataset ) { protected void handlePid(Dataset theDataset, CommandContext ctxt) throws CommandException { PidProvider pidProvider = PidUtil.getPidProvider(theDataset.getGlobalId().getProviderId()); if(!pidProvider.canManagePID()) { - throw new IllegalCommandException("PID Provider " + pidProvider.getProviderInformation().get(0) + " is not configured.", this); + throw new IllegalCommandException("PID Provider " + pidProvider.getId() + " is not configured.", this); } if ( !pidProvider.registerWhenPublished() ) { // pre-register a persistent id diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java index 6b714f9a755..8ba6d082e67 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java @@ -81,7 +81,7 @@ public boolean alreadyRegistered(GlobalId pid, boolean noProviderDefault) { public String createIdentifier(DvObject dvObject) throws Exception { logger.log(Level.FINE, "createIdentifier"); if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { - dvObject = generateIdentifier(dvObject); + dvObject = generatePid(dvObject); } String identifier = getIdentifier(dvObject); Map metadata = getMetadataForCreateIndicator(dvObject); @@ -239,7 +239,7 @@ private void deleteDraftIdentifier(DvObject dvObject) throws IOException { public boolean publicizeIdentifier(DvObject dvObject) { logger.log(Level.FINE, "updateIdentifierStatus"); if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { - dvObject = generateIdentifier(dvObject); + dvObject = generatePid(dvObject); } String identifier = getIdentifier(dvObject); Map metadata = getUpdateMetadata(dvObject); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java index 31b23080526..cedf0b4d204 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java @@ -238,7 +238,7 @@ public List getProviderInformation(){ public String createIdentifier(DvObject dvObject) throws Throwable { logger.log(Level.FINE, "createIdentifier"); if(dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty() ){ - dvObject = generateIdentifier(dvObject); + dvObject = generatePid(dvObject); } String identifier = getIdentifier(dvObject); Map metadata = getMetadataForCreateIndicator(dvObject); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java index e8f9fa8eaab..ed248375933 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java @@ -405,7 +405,7 @@ public String createIdentifier(DvObject dvObject) throws Throwable { @Override public boolean publicizeIdentifier(DvObject dvObject) { if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()){ - generateIdentifier(dvObject); + generatePid(dvObject); } return updateIdentifierStatus(dvObject, "public"); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java index 9f48f39239e..0a28fb0d5f1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java @@ -102,7 +102,7 @@ public boolean publicizeIdentifier(DvObject dvObject) { // Generate if needed (i.e. datafile case where we don't create/register early // (even with registerWhenPublished == false)) if (dvObject.getIdentifier() == null || dvObject.getIdentifier().isEmpty()) { - dvObject = generateIdentifier(dvObject); + dvObject = generatePid(dvObject); } // Call external resolver and send landing URL? return true; @@ -138,10 +138,10 @@ public GlobalId parsePersistentId(String protocol, String identifierString) { */ if(identifierString.length() < 4) { return new GlobalId(protocol, "", identifierString, SEPARATOR, getUrlPrefix(), - getProviderInformation().get(0)); + getId()); } return new GlobalId(protocol, identifierString.substring(0,4), identifierString.substring(4), SEPARATOR, getUrlPrefix(), - getProviderInformation().get(0)); + getId()); } String identifier = null; if (getAuthority() != null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index d73f39257c3..0a024b5002a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -54,7 +54,7 @@ public interface PidProvider { Map getMetadataForTargetURL(DvObject dvObject); - DvObject generateIdentifier(DvObject dvObject); + DvObject generatePid(DvObject dvObject); String getIdentifier(DvObject dvObject); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index d60d317b79e..055daaaa8a8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -102,8 +102,10 @@ private void loadProviderFactories() { */ loader.forEach(providerFactory -> { String type = providerFactory.getType(); + logger.fine("Loaded PidProviderFactory of type: " + type); // If no entry for this providerName yet or if it is an external exporter if (!pidProviderFactoryMap.containsKey(type) || providerFactory.getClass().getClassLoader().equals(cl)) { + logger.fine("Adding PidProviderFactory of type: " + type + " to the map"); pidProviderFactoryMap.put(type, providerFactory); } logger.log(Level.FINE, diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 9f283c16dda..a2a22b67a1b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -126,7 +126,7 @@ public static void addToProviderList(PidProvider pidProvider) { public static void addAllToUnmanagedProviderList(List list) { for (PidProvider pidProvider : list) { - unmanagedProviderMap.put(pidProvider.getProviderInformation().get(0), pidProvider); + unmanagedProviderMap.put(pidProvider.getId(), pidProvider); } } From f46aefc5e94b139956b7b8bcf40a00d73024e7f2 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 14:03:22 -0500 Subject: [PATCH 041/113] verify protocol/auth are set/match the provider plus cleanup --- .../pidproviders/AbstractPidProvider.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index d64bd1dd05b..24c015eb7d3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -183,20 +183,27 @@ public boolean alreadyRegistered(DvObject dvo) throws Exception { * that would be done at construction.) */ @Override - public DvObject generateIdentifier(DvObject dvObject) { + public DvObject generatePid(DvObject dvObject) { - String protocol = dvObject.getProtocol() == null ? getProtocol() : dvObject.getProtocol(); - String authority = dvObject.getAuthority() == null ? getAuthority() : dvObject.getAuthority(); - if (dvObject.isInstanceofDataset()) { - dvObject.setIdentifier(generateDatasetIdentifier((Dataset) dvObject)); - } else { - dvObject.setIdentifier(generateDataFileIdentifier((DataFile) dvObject)); - } if (dvObject.getProtocol() == null) { dvObject.setProtocol(protocol); + } else { + if (!dvObject.getProtocol().equals(getProtocol())) { + logger.warning("The protocol of the DvObject (" + dvObject.getProtocol() + ") does not match the configured protocol (" + getProtocol() + ")"); + throw new IllegalArgumentException("The protocol of the DvObject (" + dvObject.getProtocol() + ") doesn't match that of the provider, id: " + getId()); + } } if (dvObject.getAuthority() == null) { dvObject.setAuthority(authority); + } else { + logger.warning("The authority of the DvObject (" + dvObject.getAuthority() + ") does not match the configured authority (" + getAuthority() + ")"); + throw new IllegalArgumentException("The authority of the DvObject (" + dvObject.getAuthority() + ") doesn't match that of the provider, id: " + getId()); + + } + if (dvObject.isInstanceofDataset()) { + dvObject.setIdentifier(generateDatasetIdentifier((Dataset) dvObject)); + } else { + dvObject.setIdentifier(generateDataFileIdentifier((DataFile) dvObject)); } return dvObject; } @@ -308,7 +315,7 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { } public GlobalId parsePersistentId(String protocol, String authority, String identifier) { - logger.fine("Parsing: " + protocol + ":" + authority + getSeparator() + identifier + " in " + getProviderInformation().get(0)); + logger.fine("Parsing: " + protocol + ":" + authority + getSeparator() + identifier + " in " + getId()); if(!PidProvider.isValidGlobalId(protocol, authority, identifier)) { return null; } @@ -333,7 +340,7 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden } } return new GlobalId(protocol, authority, identifier, getSeparator(), getUrlPrefix(), - getProviderInformation().get(0)); + getId()); } @@ -384,7 +391,7 @@ private String generateIdentifierAsRandomString(DvObject dvo, String prepend) { String identifier = null; do { identifier = prepend + RandomStringUtils.randomAlphanumeric(6).toUpperCase(); - } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getProviderInformation().get(0)))); + } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); return identifier; } @@ -405,7 +412,7 @@ private String generateIdentifierFromStoredProcedureIndependent(DvObject dvo, St return null; } identifier = prepend + identifierFromStoredProcedure; - } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getProviderInformation().get(0)))); + } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); return identifier; } @@ -432,7 +439,7 @@ private String generateIdentifierFromStoredProcedureDependent(DataFile datafile, retVal++; identifier = prepend + retVal.toString(); - } while (existingIdentifiers.contains(identifier) || !isGlobalIdUnique(new GlobalId(datafile.getProtocol(), datafile.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getProviderInformation().get(0)))); + } while (existingIdentifiers.contains(identifier) || !isGlobalIdUnique(new GlobalId(datafile.getProtocol(), datafile.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); return identifier; } From 0f3d24f3dcaf4d350adb38c29baaf8cb0dc63afb Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 14:07:26 -0500 Subject: [PATCH 042/113] only call getGlobalId() when one should exist --- .../edu/harvard/iq/dataverse/DatasetPage.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 50a1b594a2d..16e5e880d42 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -2326,15 +2326,17 @@ private void displayLockInfo(Dataset dataset) { lockedDueToIngestVar = true; } - // With DataCite, we try to reserve the DOI when the dataset is created. Sometimes this - // fails because DataCite is down. We show the message below to set expectations that the - // "Publish" button won't work until the DOI has been reserved using the "Reserve PID" API. - PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderId()); - if (DataCiteDOIProvider.TYPE.equals(pidProvider.getProviderType()) && dataset.getGlobalIdCreateTime() == null && editMode != EditMode.CREATE) { - JH.addMessage(FacesMessage.SEVERITY_WARN, BundleUtil.getStringFromBundle("dataset.locked.pidNotReserved.message"), - BundleUtil.getStringFromBundle("dataset.locked.pidNotReserved.message.details")); + if (dataset.getGlobalIdCreateTime() == null && editMode != EditMode.CREATE) { + // With DataCite, we try to reserve the DOI when the dataset is created. Sometimes this + // fails because DataCite is down. We show the message below to set expectations that the + // "Publish" button won't work until the DOI has been reserved using the "Reserve PID" API. + PidProvider pidProvider = PidUtil.getPidProvider(dataset.getGlobalId().getProviderId()); + if (DataCiteDOIProvider.TYPE.equals(pidProvider.getProviderType())) { + JH.addMessage(FacesMessage.SEVERITY_WARN, + BundleUtil.getStringFromBundle("dataset.locked.pidNotReserved.message"), + BundleUtil.getStringFromBundle("dataset.locked.pidNotReserved.message.details")); + } } - //if necessary refresh publish message also displayPublishMessage(); From 17dada65e849ad35e167124273693366567db735 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 14:36:50 -0500 Subject: [PATCH 043/113] force all calls to create identifier to set protocol/auth as well --- .../edu/harvard/iq/dataverse/DatasetPage.java | 4 +--- .../iq/dataverse/S3PackageImporter.java | 10 +-------- .../importer/filesystem/FileRecordWriter.java | 8 +------ .../impl/AbstractCreateDatasetCommand.java | 4 ++-- .../command/impl/AbstractDatasetCommand.java | 2 +- .../command/impl/RegisterDvObjectCommand.java | 22 ++----------------- .../pidproviders/AbstractPidProvider.java | 11 ++++------ .../dataverse/pidproviders/PidProvider.java | 2 -- 8 files changed, 12 insertions(+), 51 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 16e5e880d42..cd63f8c92a7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -2108,8 +2108,6 @@ private String init(boolean initFull) { editMode = EditMode.CREATE; selectedHostDataverse = dataverseService.find(ownerId); dataset.setOwner(selectedHostDataverse); - dataset.setProtocol(protocol); - dataset.setAuthority(authority); if (dataset.getOwner() == null) { return permissionsWrapper.notFound(); @@ -2121,7 +2119,7 @@ private String init(boolean initFull) { if ( isEmpty(dataset.getIdentifier()) && systemConfig.directUploadEnabled(dataset) ) { CommandContext ctxt = commandEngine.getContext(); PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(dataset); - dataset.setIdentifier(pidProvider.generateDatasetIdentifier(dataset)); + pidProvider.generatePid(dataset); } dataverseTemplates.addAll(dataverseService.find(ownerId).getTemplates()); if (!dataverseService.find(ownerId).isTemplateRoot()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java index 7d97353d6d9..a387b27d98b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java @@ -206,15 +206,7 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t FileUtil.generateS3PackageStorageIdentifier(packageFile); PidProvider pidProvider = commandEngine.getContext().dvObjects().getEffectivePidGenerator(dataset); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { - String packageIdentifier = pidProvider.generateDataFileIdentifier(packageFile); - packageFile.setIdentifier(packageIdentifier); - } - - if (packageFile.getProtocol() == null) { - packageFile.setProtocol(pidProvider.getProtocol()); - } - if (packageFile.getAuthority() == null) { - packageFile.setAuthority(pidProvider.getAuthority()); + pidProvider.generatePid(packageFile); } if (!packageFile.isIdentifierRegistered()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java index 6899856683d..af1e9c6a294 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordWriter.java @@ -362,13 +362,7 @@ private DataFile createPackageDataFile(List files) { PidProvider pidProvider = commandEngine.getContext().dvObjects().getEffectivePidGenerator(dataset); if (packageFile.getIdentifier() == null || packageFile.getIdentifier().isEmpty()) { - packageFile.setIdentifier(pidProvider.generateDataFileIdentifier(packageFile)); - } - if (packageFile.getProtocol() == null) { - packageFile.setProtocol(pidProvider.getProtocol()); - } - if (packageFile.getAuthority() == null) { - packageFile.setAuthority(pidProvider.getAuthority()); + pidProvider.generatePid(packageFile); } if (!packageFile.isIdentifierRegistered()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index b9f7c75ce78..d8302024c14 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -86,7 +86,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(theDataset); if ( isEmpty(theDataset.getIdentifier()) ) { - theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); + pidProvider.generatePid(theDataset); } DatasetVersion dsv = getVersionToPersist(theDataset); @@ -119,7 +119,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { theDataset.setStorageIdentifier(driverId + DataAccess.SEPARATOR + theDataset.getAuthorityForFileStorage() + "/" + theDataset.getIdentifierForFileStorage()); } if (theDataset.getIdentifier()==null) { - theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); + pidProvider.generatePid(theDataset); } // Attempt the registration if importing dataset through the API, or the app (but not harvest) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java index e36bf72ec0a..85e417ac5f3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java @@ -160,7 +160,7 @@ protected void registerExternalIdentifier(Dataset theDataset, CommandContext ctx int attempts = 0; if(retry) { do { - theDataset.setIdentifier(pidProvider.generateDatasetIdentifier(theDataset)); + pidProvider.generatePid(theDataset); logger.log(Level.INFO, "Attempting to register external identifier for dataset {0} (trying: {1}).", new Object[]{theDataset.getId(), theDataset.getIdentifier()}); attempts++; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java index d27a26da917..a2fe8413d9d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java @@ -52,19 +52,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { //Test to see if identifier already present //if so, leave. if (target.getIdentifier() == null || target.getIdentifier().isEmpty()) { - - if (target.isInstanceofDataset()) { - target.setIdentifier(pidProvider.generateDatasetIdentifier((Dataset) target)); - - } else { - target.setIdentifier(pidProvider.generateDataFileIdentifier((DataFile) target)); - } - if (target.getProtocol() == null) { - target.setProtocol(pidProvider.getProtocol()); - } - if (target.getAuthority() == null) { - target.setAuthority(pidProvider.getAuthority()); - } + pidProvider.generatePid(target); } if (pidProvider.alreadyRegistered(target)) { @@ -92,13 +80,7 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { Dataset dataset = (Dataset) target; for (DataFile df : dataset.getFiles()) { if (df.getIdentifier() == null || df.getIdentifier().isEmpty()) { - df.setIdentifier(pidProvider.generateDataFileIdentifier(df)); - if (df.getProtocol() == null || df.getProtocol().isEmpty()) { - df.setProtocol(pidProvider.getProtocol()); - } - if (df.getAuthority() == null || df.getAuthority().isEmpty()) { - df.setAuthority(pidProvider.getAuthority()); - } + pidProvider.generatePid(df); } doiRetString = pidProvider.createIdentifier(df); if (doiRetString != null && doiRetString.contains(df.getIdentifier())) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 24c015eb7d3..62625413835 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -186,7 +186,7 @@ public boolean alreadyRegistered(DvObject dvo) throws Exception { public DvObject generatePid(DvObject dvObject) { if (dvObject.getProtocol() == null) { - dvObject.setProtocol(protocol); + dvObject.setProtocol(getProtocol()); } else { if (!dvObject.getProtocol().equals(getProtocol())) { logger.warning("The protocol of the DvObject (" + dvObject.getProtocol() + ") does not match the configured protocol (" + getProtocol() + ")"); @@ -194,7 +194,7 @@ public DvObject generatePid(DvObject dvObject) { } } if (dvObject.getAuthority() == null) { - dvObject.setAuthority(authority); + dvObject.setAuthority(getAuthority()); } else { logger.warning("The authority of the DvObject (" + dvObject.getAuthority() + ") does not match the configured authority (" + getAuthority() + ")"); throw new IllegalArgumentException("The authority of the DvObject (" + dvObject.getAuthority() + ") doesn't match that of the provider, id: " + getId()); @@ -208,9 +208,7 @@ public DvObject generatePid(DvObject dvObject) { return dvObject; } - //ToDo just send the DvObject.DType - public String generateDatasetIdentifier(Dataset dataset) { - //ToDo - track these in the bean + private String generateDatasetIdentifier(Dataset dataset) { String shoulder = getShoulder(); switch (getIdentifierGenerationStyle()) { @@ -349,8 +347,7 @@ public String getSeparator() { return SEPARATOR; } - @Override - public String generateDataFileIdentifier(DataFile datafile) { + private String generateDataFileIdentifier(DataFile datafile) { String doiDataFileFormat = getDatafilePidFormat(); String prepend = ""; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index 0a024b5002a..2b2fe2ee07b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -60,8 +60,6 @@ public interface PidProvider { boolean publicizeIdentifier(DvObject studyIn); - String generateDatasetIdentifier(Dataset dataset); - String generateDataFileIdentifier(DataFile datafile); boolean isGlobalIdUnique(GlobalId globalId); String getUrlPrefix(); From c80ddd1abea96e7755ea293427812be6e2022c39 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 16:19:21 -0500 Subject: [PATCH 044/113] move template to match refactor --- .../{ => pidproviders/datacite}/datacite_metadata_template.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/edu/harvard/iq/dataverse/{ => pidproviders/datacite}/datacite_metadata_template.xml (100%) diff --git a/src/main/resources/edu/harvard/iq/dataverse/datacite_metadata_template.xml b/src/main/resources/edu/harvard/iq/dataverse/pidproviders/datacite/datacite_metadata_template.xml similarity index 100% rename from src/main/resources/edu/harvard/iq/dataverse/datacite_metadata_template.xml rename to src/main/resources/edu/harvard/iq/dataverse/pidproviders/datacite/datacite_metadata_template.xml From 03d86f150ec8b7f8eb37e37eb8b8cbbde7e0dc2a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 16:19:40 -0500 Subject: [PATCH 045/113] require superuser to change PidProvider --- src/main/webapp/dataverse.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index 5d05cb50285..da984abcb34 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -283,7 +283,7 @@
-
+
#{bundle.pidProviderOption} Date: Thu, 11 Jan 2024 17:39:10 -0500 Subject: [PATCH 046/113] cleanup --- .../FinalizeDatasetPublicationCommand.java | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java index eea66d8b38a..1b08ae24348 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java @@ -386,56 +386,52 @@ private void validateDataFiles(Dataset dataset, CommandContext ctxt) throws Comm } private void publicizeExternalIdentifier(Dataset dataset, CommandContext ctxt) throws CommandException { - String protocol = getDataset().getProtocol(); - String authority = getDataset().getAuthority(); - PidProvider pidProvider = PidUtil.getPidProvider(getDataset().getGlobalId().getProviderId()); - - if (pidProvider != null) { - - try { - boolean isFilePIDsEnabled = ctxt.systemConfig().isFilePIDsEnabledForCollection(getDataset().getOwner()); - // We will skip trying to register the global identifiers for datafiles - // if "dependent" file-level identifiers are requested, AND the naming - // protocol, or the authority of the dataset global id is different from - // what's currently configured for the Dataverse. In other words - // we can't get "dependent" DOIs assigned to files in a dataset - // with the registered id that is a handle; or even a DOI, but in - // an authority that's different from what's currently configured. - // Additionaly in 4.9.3 we have added a system variable to disable - // registering file PIDs on the installation level. - boolean registerGlobalIdsForFiles = - ctxt.systemConfig().isFilePIDsEnabledForCollection(getDataset().getOwner()) && - ctxt.dvObjects().getEffectivePidGenerator(dataset).canCreatePidsLike(dataset.getGlobalId()); - - if (registerGlobalIdsForFiles - && isFilePIDsEnabled - && dataset.getLatestVersion().getMinorVersionNumber() != null - && dataset.getLatestVersion().getMinorVersionNumber().equals((long) 0)) { - //A false return value indicates a failure in calling the service - for (DataFile df : dataset.getFiles()) { - logger.log(Level.FINE, "registering global id for file {0}", df.getId()); - //A false return value indicates a failure in calling the service - if (!pidProvider.publicizeIdentifier(df)) { - throw new Exception(); - } - df.setGlobalIdCreateTime(getTimestamp()); - df.setIdentifierRegistered(true); + PidProvider pidProvider = ctxt.dvObjects().getEffectivePidGenerator(dataset); + try { + // We will skip trying to register the global identifiers for datafiles + // if "dependent" file-level identifiers are requested, AND the naming + // protocol, or the authority of the dataset global id is different from + // what's currently configured for the Dataverse. In other words + // we can't get "dependent" DOIs assigned to files in a dataset + // with the registered id that is a handle; or even a DOI, but in + // an authority that's different from what's currently configured. + // Additionaly in 4.9.3 we have added a system variable to disable + // registering file PIDs on the installation level. + boolean registerGlobalIdsForFiles = ctxt.systemConfig().isFilePIDsEnabledForCollection( + getDataset().getOwner()) + && pidProvider.canCreatePidsLike(dataset.getGlobalId()); + + if (registerGlobalIdsForFiles + && dataset.getLatestVersion().getMinorVersionNumber() != null + && dataset.getLatestVersion().getMinorVersionNumber().equals((long) 0)) { + // A false return value indicates a failure in calling the service + for (DataFile df : dataset.getFiles()) { + logger.log(Level.FINE, "registering global id for file {0}", df.getId()); + // A false return value indicates a failure in calling the service + if (!pidProvider.publicizeIdentifier(df)) { + throw new Exception(); } + df.setGlobalIdCreateTime(getTimestamp()); + df.setIdentifierRegistered(true); } - if (!pidProvider.publicizeIdentifier(dataset)) { - throw new Exception(); - } - dataset.setGlobalIdCreateTime(new Date()); // TODO these two methods should be in the responsibility of the pidProvider. - dataset.setIdentifierRegistered(true); - } catch (Throwable e) { - logger.warning("Failed to register the identifier "+dataset.getGlobalId().asString()+", or to register a file in the dataset; notifying the user(s), unlocking the dataset"); - - // Send failure notification to the user: - notifyUsersDatasetPublishStatus(ctxt, dataset, UserNotification.Type.PUBLISHFAILED_PIDREG); - - ctxt.datasets().removeDatasetLocks(dataset, DatasetLock.Reason.finalizePublication); - throw new CommandException(BundleUtil.getStringFromBundle("dataset.publish.error", pidProvider.getProviderInformation()), this); } + if (!pidProvider.publicizeIdentifier(dataset)) { + throw new Exception(); + } + dataset.setGlobalIdCreateTime(new Date()); // TODO these two methods should be in the responsibility of the + // pidProvider. + dataset.setIdentifierRegistered(true); + } catch (Throwable e) { + logger.warning("Failed to register the identifier " + dataset.getGlobalId().asString() + + ", or to register a file in the dataset; notifying the user(s), unlocking the dataset"); + + // Send failure notification to the user: + notifyUsersDatasetPublishStatus(ctxt, dataset, UserNotification.Type.PUBLISHFAILED_PIDREG); + + ctxt.datasets().removeDatasetLocks(dataset, DatasetLock.Reason.finalizePublication); + throw new CommandException( + BundleUtil.getStringFromBundle("dataset.publish.error", pidProvider.getProviderInformation()), + this); } } From 2b039f22eb9fdec52df5d0a644f870420f9e80c6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 17:39:32 -0500 Subject: [PATCH 047/113] check can create method --- .../java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index c01c0f52ba9..ecef047b0cb 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -366,6 +366,7 @@ public void testFindingPidGenerators() throws IOException { dataset1.setPidGenerator(null); assertEquals("dc1", dataset1.getGlobalId().getProviderId()); assertEquals("dc1", dataset1.getEffectivePidGenerator().getId()); + assertTrue(PidUtil.getPidProvider(dataset1.getEffectivePidGenerator().getId()).canCreatePidsLike(dataset1.getGlobalId())); dataset1.setPidGenerator(null); //Now set identifier so that the provider has this one in it's managed list (and therefore we can't mint new PIDs in the same auth/shoulder) and therefore we get the effective pid generator @@ -374,5 +375,6 @@ public void testFindingPidGenerators() throws IOException { assertEquals("ez1", dataset1.getEffectivePidGenerator().getId()); + } } From 5f4d8a922d5236bb33523c41fa41d8d71f0b887b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 11 Jan 2024 17:39:50 -0500 Subject: [PATCH 048/113] make fake provider create file pids --- .../harvard/iq/dataverse/pidproviders/FakeDOIProvider.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java index df57677e136..cf8f0951b53 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java @@ -64,7 +64,10 @@ public void deleteIdentifier(DvObject dvo) throws Exception { } @Override - public boolean publicizeIdentifier(DvObject studyIn) { + public boolean publicizeIdentifier(DvObject dvObject) { + if(dvObject.isInstanceofDataFile() && dvObject.getGlobalId()==null) { + generatePid(dvObject); + } return true; } From 0dfa0a0890456e87e02657569c2a06ca451a5253 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 14:46:58 -0500 Subject: [PATCH 049/113] typo - fix UI --- src/main/webapp/dataverse.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index da984abcb34..7f70f28e194 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -290,7 +290,7 @@ data-toggle="tooltip" data-placement="auto right" data-original-title="#{bundle['dataverse.pidProvider.title']}">
- + From 1a32732eafea0749454b4a82715028638d9b2bda Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 14:47:12 -0500 Subject: [PATCH 050/113] return default instead of null for UI --- .../edu/harvard/iq/dataverse/DvObjectContainer.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java index 9fe1aef9423..c991c4c02d2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectContainer.java @@ -200,11 +200,16 @@ public void setPidGeneratorSpecs(String pidGeneratorSpecs) { this.pidGeneratorSpecs = pidGeneratorSpecs; } - //Used in JSF when selecting the PidGenerator + // Used in JSF when selecting the PidGenerator public String getPidGeneratorId() { - return getEffectivePidGenerator().getId(); + PidProvider pidGenerator = getEffectivePidGenerator(); + if (pidGenerator == null) { + return "default"; + } else { + return getEffectivePidGenerator().getId(); + } } - + //Used in JSF when setting the PidGenerator public void setPidGeneratorId(String pidGeneratorId) { // Note that the "default" provider will not be found so will result in From 831e7db0b2426e45f6101e1d1137b9d50e6b7935 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 14:48:39 -0500 Subject: [PATCH 051/113] unrelated - logic fix --- .../engine/command/impl/FinalizeDatasetPublicationCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java index 1b08ae24348..37aeee231e1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/FinalizeDatasetPublicationCommand.java @@ -351,7 +351,7 @@ private void validateDataFiles(Dataset dataset, CommandContext ctxt) throws Comm // major release; we can revisit the decision if there's any // indication that this makes publishing take significantly longer. String driverId = FileUtil.getStorageDriver(dataFile); - if(StorageIO.isDataverseAccessible(driverId) && maxFileSize == -1 || dataFile.getFilesize() < maxFileSize) { + if(StorageIO.isDataverseAccessible(driverId) && (maxFileSize == -1 || dataFile.getFilesize() < maxFileSize)) { FileUtil.validateDataFileChecksum(dataFile); } else { From 25087219e45d4b94c5ef03e440553645abd59d4c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 14:50:38 -0500 Subject: [PATCH 052/113] partial support for legacy config - FAKE and DatCite - for testing --- .../pidproviders/PidProviderFactoryBean.java | 74 +++++++++++++++---- .../iq/dataverse/settings/JvmSettings.java | 11 ++- .../settings/SettingsServiceBean.java | 4 +- .../dataverse/pidproviders/PidUtilTest.java | 63 ++++++++++++++++ 4 files changed, 135 insertions(+), 17 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 055daaaa8a8..fd6d7909623 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -12,14 +12,12 @@ 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.Set; import java.util.logging.Level; import java.util.logging.Logger; -import org.eclipse.microprofile.config.ConfigProvider; - import jakarta.annotation.PostConstruct; import jakarta.ejb.EJB; import jakarta.ejb.Singleton; @@ -29,11 +27,8 @@ import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; import edu.harvard.iq.dataverse.DataverseServiceBean; -import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.pidproviders.PidProvider; -import io.gdcc.spi.export.Exporter; /** * This Bean loads all of the PidProviderFactory types available (e.g. EZID, @@ -116,14 +111,67 @@ private void loadProviderFactories() { } private void loadProviders() { - String[] providers = JvmSettings.PID_PROVIDERS.lookup(String[].class); - for (String name : providers) { - String type = JvmSettings.PID_PROVIDER_TYPE.lookup(name); - if (pidProviderFactoryMap.containsKey(type)) { - PidProvider provider = pidProviderFactoryMap.get(type).createPidProvider(name); - provider.setPidProviderServiceBean(this); - PidUtil.addToProviderList(provider); + try { + String[] providers = JvmSettings.PID_PROVIDERS.lookup(String[].class); + for (String name : providers) { + String type = JvmSettings.PID_PROVIDER_TYPE.lookup(name); + if (pidProviderFactoryMap.containsKey(type)) { + PidProvider provider = pidProviderFactoryMap.get(type).createPidProvider(name); + provider.setPidProviderServiceBean(this); + PidUtil.addToProviderList(provider); + } + } + } catch (NoSuchElementException e) { + logger.warning("No PidProviders configured"); + } + String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol); + String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority); + String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder); + String provider = settingsService.getValueForKey(SettingsServiceBean.Key.DoiProvider); + + if (protocol != null && authority != null && shoulder != null && provider != null) { + logger.warning("Found legacy settings: " + protocol + " " + authority + " " + shoulder + " " + provider); + if (PidUtil.getPidProvider(protocol, authority, shoulder) == null) { + PidProvider legacy = null; + // Try to add a legacy provider + String identifierGenerationStyle = settingsService + .getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "random"); + String dataFilePidFormat = settingsService.getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, + "DEPENDENT"); + switch (provider) { + case "EZID": + /* + * String baseUrl = JvmSettings.PID_EZID_BASE_URL.lookup(String.class); String + * username = JvmSettings.PID_EZID_USERNAME.lookup(String.class); String + * password = JvmSettings.PID_EZID_PASSWORD.lookup(String.class); + * PidUtil.addToProviderList( new EZIdDOIProvider("legacy", "legacy", authority, + * shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", baseUrl, + * username, password)); + */ + break; + case "DataCite": + String mdsUrl = JvmSettings.LEGACY_DATACITE_MDS_API_URL.lookup(String.class); + String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(String.class); + String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class); + String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class); + if (mdsUrl == null || restUrl == null || dcUsername == null || dcPassword == null) { + legacy = new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, + dcPassword); + } + break; + case "FAKE": + logger.warning("Adding FAKE provider"); + legacy = new FakeDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", ""); + break; + } + legacy.setPidProviderServiceBean(this); + PidUtil.addToProviderList(legacy); + } else { + logger.warning("Legacy PID provider settings found - ignored since a provider for the same protocol, authority, shoulder has been registered"); } + logger.info("Have " + PidUtil.getManagedProviderIds().size() + " managed PID providers"); } PidUtil.addAllToUnmanagedProviderList(Arrays.asList(new UnmanagedDOIProvider(), new UnmanagedHandlePidProvider(), new UnmanagedPermaLinkPidProvider())); diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index c6d04f4ec4b..fcc1a2bc963 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -103,8 +103,15 @@ public enum JvmSettings { PID_PROVIDER_DATAFILE_PID_FORMAT(SCOPE_PID_PROVIDER, "datafile-pid-format"), PID_PROVIDER_MANAGED_LIST(SCOPE_PID_PROVIDER, "managed-list"), PID_PROVIDER_EXCLUDED_LIST(SCOPE_PID_PROVIDER, "excluded-list"), - - // PROVIDER EZID (legacy) - these settings were formerly kept together with DataCite ones + + // PROVIDER DATACITE (legacy - single provider setting) + SCOPE_LEGACY_PID_DATACITE(SCOPE_PID, "datacite"), + LEGACY_DATACITE_MDS_API_URL(SCOPE_LEGACY_PID_DATACITE, "mds-api-url"), + LEGACY_DATACITE_REST_API_URL(SCOPE_LEGACY_PID_DATACITE, "rest-api-url"), + LEGACY_DATACITE_USERNAME(SCOPE_LEGACY_PID_DATACITE, "username"), + LEGACY_DATACITE_PASSWORD(SCOPE_LEGACY_PID_DATACITE, "password"), + + // PROVIDER EZID - these settings were formerly kept together with DataCite ones SCOPE_PID_EZID(SCOPE_PID_PROVIDER, "ezid"), EZID_API_URL(SCOPE_PID_EZID, "api-url"), EZID_USERNAME(SCOPE_PID_EZID, "username"), diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 047fdfc3202..29f17b6bcec 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -194,7 +194,7 @@ public enum Key { /** authority for global id */ Authority, /** DoiProvider for global id */ - //DoiProvider, + DoiProvider, /** Shoulder for global id - used to create a common prefix on identifiers */ Shoulder, /* Removed for now - tried to add here but DOI Service Bean didn't like it at start-up @@ -351,7 +351,7 @@ Whether Harvesting (OAI) service is enabled 'DEPENEDENT' means the DOI will be the Dataset DOI plus a file DOI with a slash in between. 'INDEPENDENT' means a new global id, completely independent from the dataset-level global id. */ - //DataFilePIDFormat, + DataFilePIDFormat, /* Json array of supported languages */ Languages, diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index ecef047b0cb..5b2bac105de 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -377,4 +377,67 @@ public void testFindingPidGenerators() throws IOException { } + + @Test + public void testLegacyConfig() throws IOException { + MockitoAnnotations.openMocks(this); + Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider)).thenReturn("FAKE"); + Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Shoulder)).thenReturn("FK2"); + + Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol)).thenReturn("doi"); + Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("10.5072"); + + String protocol = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol); + String authority = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority); + String shoulder = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Shoulder); + String provider = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider); + + PidUtil.clearPidProviders(); + if (protocol != null && authority != null && shoulder != null && provider != null) { + System.out.println("Looking"); + if (PidUtil.getPidProvider(protocol, authority, shoulder) == null) { + // Try to add a legacy provider + String identifierGenerationStyle = settingsServiceBean + .getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "random"); + String dataFilePidFormat = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, + "DEPENDENT"); + switch (provider) { + case "EZID": + /* + * String baseUrl = JvmSettings.PID_EZID_BASE_URL.lookup(String.class); String + * username = JvmSettings.PID_EZID_USERNAME.lookup(String.class); String + * password = JvmSettings.PID_EZID_PASSWORD.lookup(String.class); + * PidUtil.addToProviderList( new EZIdDOIProvider("legacy", "legacy", authority, + * shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", baseUrl, + * username, password)); + */ + break; + case "DataCite": + String mdsUrl = JvmSettings.LEGACY_DATACITE_MDS_API_URL.lookup(String.class); + String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(String.class); + String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class); + String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class); + if (mdsUrl == null || restUrl == null || dcUsername == null || dcPassword == null) { + PidUtil.addToProviderList(new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, + dcPassword)); + } + break; + case "FAKE": + System.out.println("Legacy FAKE found"); + PidUtil.addToProviderList(new FakeDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", "")); + break; + } + } else { + System.out.println("Legacy PID provider settings found - ignored since a provider for the same protocol, authority, shoulder has been registered"); + } + + } + + String pid1String = "doi:10.5072/FK2ABCDEF"; + GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); + assertEquals(pid1String, pid2.asString()); + assertEquals("legacy", pid2.getProviderId()); + } } From 34c53612556b0723b676a0b6b1659cb9e2048d6b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 14:50:51 -0500 Subject: [PATCH 053/113] cleanup --- .../java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index a2a22b67a1b..54f39fc1e1a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -246,11 +246,6 @@ public static void clearPidProviders() { unmanagedProviderMap.clear(); } - public static PidProvider getDefaultPidGenerator() { - // TODO Auto-generated method stub - return null; - } - /** * Get a PidProvider by protocol/authority/shoulder. */ From d04b56a127a9ca68d6c662ec78eb48d9dd655ddc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 15:03:47 -0500 Subject: [PATCH 054/113] style fail --- .../pidproviders/AbstractPidProvider.java | 674 +++++++++--------- 1 file changed, 354 insertions(+), 320 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 62625413835..b2c69b72aaa 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -19,15 +19,13 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; - - public abstract class AbstractPidProvider implements PidProvider { private static final Logger logger = Logger.getLogger(AbstractPidProvider.class.getCanonicalName()); public static String UNAVAILABLE = ":unav"; public static final String SEPARATOR = "/"; - + PidProviderFactoryBean pidProviderService; private String protocol; @@ -46,17 +44,17 @@ public abstract class AbstractPidProvider implements PidProvider { private String id; private String label; - - AbstractPidProvider(String id, String label, String protocol) - { + + AbstractPidProvider(String id, String label, String protocol) { this.id = id; this.label = label; this.protocol = protocol; - this.managedSet = new HashSet(); + this.managedSet = new HashSet(); this.excludedSet = new HashSet(); } - - AbstractPidProvider(String id, String label, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + + AbstractPidProvider(String id, String label, String protocol, String authority, String shoulder, + String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { this.id = id; this.label = label; this.protocol = protocol; @@ -77,10 +75,10 @@ public abstract class AbstractPidProvider implements PidProvider { } } } - + @Override public Map getMetadataForCreateIndicator(DvObject dvObjectIn) { - logger.log(Level.FINE,"getMetadataForCreateIndicator(DvObject)"); + logger.log(Level.FINE, "getMetadataForCreateIndicator(DvObject)"); Map metadata = new HashMap<>(); metadata = addBasicMetadata(dvObjectIn, metadata); metadata.put("datacite.publicationyear", generateYear(dvObjectIn)); @@ -89,12 +87,12 @@ public Map getMetadataForCreateIndicator(DvObject dvObjectIn) { } protected Map getUpdateMetadata(DvObject dvObjectIn) { - logger.log(Level.FINE,"getUpdateMetadataFromDataset"); + logger.log(Level.FINE, "getUpdateMetadataFromDataset"); Map metadata = new HashMap<>(); metadata = addBasicMetadata(dvObjectIn, metadata); return metadata; } - + protected Map addBasicMetadata(DvObject dvObjectIn, Map metadata) { String authorString = dvObjectIn.getAuthorString(); @@ -119,8 +117,8 @@ protected Map addBasicMetadata(DvObject dvObjectIn, Map addDOIMetadataForDestroyedDataset(DvObject dvObjectIn) { Map metadata = new HashMap<>(); String authorString = UNAVAILABLE; @@ -132,38 +130,39 @@ protected Map addDOIMetadataForDestroyedDataset(DvObject dvObjec metadata.put("datacite.publisher", producerString); metadata.put("datacite.publicationyear", "9999"); return metadata; - } + } protected String getTargetUrl(DvObject dvObjectIn) { - logger.log(Level.FINE,"getTargetUrl"); - return SystemConfig.getDataverseSiteUrlStatic() + dvObjectIn.getTargetUrl() + dvObjectIn.getGlobalId().asString(); + logger.log(Level.FINE, "getTargetUrl"); + return SystemConfig.getDataverseSiteUrlStatic() + dvObjectIn.getTargetUrl() + + dvObjectIn.getGlobalId().asString(); } - + @Override public String getIdentifier(DvObject dvObject) { GlobalId gid = dvObject.getGlobalId(); return gid != null ? gid.asString() : null; } - protected String generateYear (DvObject dvObjectIn){ - return dvObjectIn.getYearPublishedCreated(); + protected String generateYear(DvObject dvObjectIn) { + return dvObjectIn.getYearPublishedCreated(); } - + public Map getMetadataForTargetURL(DvObject dvObject) { - logger.log(Level.FINE,"getMetadataForTargetURL"); + logger.log(Level.FINE, "getMetadataForTargetURL"); HashMap metadata = new HashMap<>(); metadata.put("_target", getTargetUrl(dvObject)); return metadata; } - + @Override public boolean alreadyRegistered(DvObject dvo) throws Exception { - if(dvo==null) { + if (dvo == null) { logger.severe("Null DvObject sent to alreadyRegistered()."); return false; } GlobalId globalId = dvo.getGlobalId(); - if(globalId == null) { + if (globalId == null) { return false; } return alreadyRegistered(globalId, false); @@ -189,16 +188,20 @@ public DvObject generatePid(DvObject dvObject) { dvObject.setProtocol(getProtocol()); } else { if (!dvObject.getProtocol().equals(getProtocol())) { - logger.warning("The protocol of the DvObject (" + dvObject.getProtocol() + ") does not match the configured protocol (" + getProtocol() + ")"); - throw new IllegalArgumentException("The protocol of the DvObject (" + dvObject.getProtocol() + ") doesn't match that of the provider, id: " + getId()); + logger.warning("The protocol of the DvObject (" + dvObject.getProtocol() + + ") does not match the configured protocol (" + getProtocol() + ")"); + throw new IllegalArgumentException("The protocol of the DvObject (" + dvObject.getProtocol() + + ") doesn't match that of the provider, id: " + getId()); } } if (dvObject.getAuthority() == null) { dvObject.setAuthority(getAuthority()); } else { - logger.warning("The authority of the DvObject (" + dvObject.getAuthority() + ") does not match the configured authority (" + getAuthority() + ")"); - throw new IllegalArgumentException("The authority of the DvObject (" + dvObject.getAuthority() + ") doesn't match that of the provider, id: " + getId()); - + logger.warning("The authority of the DvObject (" + dvObject.getAuthority() + + ") does not match the configured authority (" + getAuthority() + ")"); + throw new IllegalArgumentException("The authority of the DvObject (" + dvObject.getAuthority() + + ") doesn't match that of the provider, id: " + getId()); + } if (dvObject.isInstanceofDataset()) { dvObject.setIdentifier(generateDatasetIdentifier((Dataset) dvObject)); @@ -207,78 +210,76 @@ public DvObject generatePid(DvObject dvObject) { } return dvObject; } - + private String generateDatasetIdentifier(Dataset dataset) { String shoulder = getShoulder(); switch (getIdentifierGenerationStyle()) { - case "randomString": - return generateIdentifierAsRandomString(dataset, shoulder); - case "storedProcGenerated": - return generateIdentifierFromStoredProcedureIndependent(dataset, shoulder); - default: - /* Should we throw an exception instead?? -- L.A. 4.6.2 */ - return generateIdentifierAsRandomString(dataset, shoulder); + case "randomString": + return generateIdentifierAsRandomString(dataset, shoulder); + case "storedProcGenerated": + return generateIdentifierFromStoredProcedureIndependent(dataset, shoulder); + default: + /* Should we throw an exception instead?? -- L.A. 4.6.2 */ + return generateIdentifierAsRandomString(dataset, shoulder); } } - /** - * Check that a identifier entered by the user is unique (not currently used - * for any other study in this Dataverse Network) also check for duplicate - * in EZID if needed + * Check that a identifier entered by the user is unique (not currently used for + * any other study in this Dataverse Network) also check for duplicate in EZID + * if needed + * * @param userIdentifier * @param dataset * @return {@code true} if the identifier is unique, {@code false} otherwise. */ public boolean isGlobalIdUnique(GlobalId globalId) { - if ( ! pidProviderService.isGlobalIdLocallyUnique(globalId)) { + if (!pidProviderService.isGlobalIdLocallyUnique(globalId)) { return false; // duplication found in local database } // not in local DB, look in the persistent identifier service try { - return ! alreadyRegistered(globalId, false); - } catch (Exception e){ - //we can live with failure - means identifier not found remotely + return !alreadyRegistered(globalId, false); + } catch (Exception e) { + // we can live with failure - means identifier not found remotely } return true; } - /** - * Parse a Persistent Id and set the protocol, authority, and identifier + /** + * Parse a Persistent Id and set the protocol, authority, and identifier * - * Example 1: doi:10.5072/FK2/BYM3IW - * protocol: doi - * authority: 10.5072 - * identifier: FK2/BYM3IW + * Example 1: doi:10.5072/FK2/BYM3IW protocol: doi authority: 10.5072 + * identifier: FK2/BYM3IW * - * Example 2: hdl:1902.1/111012 - * protocol: hdl - * authority: 1902.1 - * identifier: 111012 + * Example 2: hdl:1902.1/111012 protocol: hdl authority: 1902.1 identifier: + * 111012 * * @param identifierString - * @param separator the string that separates the authority from the identifier. - * @param destination the global id that will contain the parsed data. + * @param separator the string that separates the authority from the + * identifier. + * @param destination the global id that will contain the parsed data. * @return {@code destination}, after its fields have been updated, or * {@code null} if parsing failed. */ @Override public GlobalId parsePersistentId(String fullIdentifierString) { // Occasionally, the protocol separator character ':' comes in still - // URL-encoded as %3A (usually as a result of the URL having been + // URL-encoded as %3A (usually as a result of the URL having been // encoded twice): fullIdentifierString = fullIdentifierString.replace("%3A", ":"); - + int index1 = fullIdentifierString.indexOf(':'); if (index1 > 0) { // ':' found with one or more characters before it String protocol = fullIdentifierString.substring(0, index1); - GlobalId globalId = parsePersistentId(protocol, fullIdentifierString.substring(index1+1)); + GlobalId globalId = parsePersistentId(protocol, fullIdentifierString.substring(index1 + 1)); return globalId; } - logger.log(Level.INFO, "Error parsing identifier: {0}: '':'' not found in string", fullIdentifierString); + logger.log(Level.INFO, "Error parsing identifier: {0}: '':'' not found in string", + fullIdentifierString); return null; } @@ -295,7 +296,7 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { // Strip any whitespace, ; and ' from authority (should finding them cause a // failure instead?) authority = PidProvider.formatIdentifierString(identifierString.substring(0, index)); - + if (PidProvider.testforNullTerminator(authority)) { return null; } @@ -311,13 +312,14 @@ protected GlobalId parsePersistentId(String protocol, String identifierString) { } return parsePersistentId(protocol, authority, identifier); } - + public GlobalId parsePersistentId(String protocol, String authority, String identifier) { logger.fine("Parsing: " + protocol + ":" + authority + getSeparator() + identifier + " in " + getId()); - if(!PidProvider.isValidGlobalId(protocol, authority, identifier)) { + if (!PidProvider.isValidGlobalId(protocol, authority, identifier)) { return null; } - //Check authority/identifier if this is a provider that manages specific identifiers + // Check authority/identifier if this is a provider that manages specific + // identifiers // /is not one of the unmanaged providers that has null authority if (getAuthority() != null) { @@ -331,379 +333,409 @@ public GlobalId parsePersistentId(String protocol, String authority, String iden logger.fine("clean pid in " + getId() + ": " + cleanIdentifier); logger.fine("managed in " + getId() + ": " + getManagedSet().contains(cleanIdentifier)); logger.fine("excluded from " + getId() + ": " + getExcludedSet().contains(cleanIdentifier)); - + if (!(((authority.equals(getAuthority()) && identifier.startsWith(getShoulder())) || getManagedSet().contains(cleanIdentifier)) && !getExcludedSet().contains(cleanIdentifier))) { return null; } } - return new GlobalId(protocol, authority, identifier, getSeparator(), getUrlPrefix(), - getId()); + return new GlobalId(protocol, authority, identifier, getSeparator(), getUrlPrefix(), getId()); } - public String getSeparator() { - //The standard default + // The standard default return SEPARATOR; } private String generateDataFileIdentifier(DataFile datafile) { String doiDataFileFormat = getDatafilePidFormat(); - + String prepend = ""; - if (doiDataFileFormat.equals(SystemConfig.DataFilePIDFormat.DEPENDENT.toString())){ - //If format is dependent then pre-pend the dataset identifier + if (doiDataFileFormat.equals(SystemConfig.DataFilePIDFormat.DEPENDENT.toString())) { + // If format is dependent then pre-pend the dataset identifier prepend = datafile.getOwner().getIdentifier() + SEPARATOR; datafile.setProtocol(datafile.getOwner().getProtocol()); datafile.setAuthority(datafile.getOwner().getAuthority()); } else { - //If there's a shoulder prepend independent identifiers with it + // If there's a shoulder prepend independent identifiers with it prepend = getShoulder(); datafile.setProtocol(getProtocol()); datafile.setAuthority(getAuthority()); } - + switch (getIdentifierGenerationStyle()) { - case "randomString": - return generateIdentifierAsRandomString(datafile, prepend); - case "storedProcGenerated": - if (doiDataFileFormat.equals(SystemConfig.DataFilePIDFormat.INDEPENDENT.toString())){ - return generateIdentifierFromStoredProcedureIndependent(datafile, prepend); - } else { - return generateIdentifierFromStoredProcedureDependent(datafile, prepend); - } - default: - /* Should we throw an exception instead?? -- L.A. 4.6.2 */ - return generateIdentifierAsRandomString(datafile, prepend); + case "randomString": + return generateIdentifierAsRandomString(datafile, prepend); + case "storedProcGenerated": + if (doiDataFileFormat.equals(SystemConfig.DataFilePIDFormat.INDEPENDENT.toString())) { + return generateIdentifierFromStoredProcedureIndependent(datafile, prepend); + } else { + return generateIdentifierFromStoredProcedureDependent(datafile, prepend); + } + default: + /* Should we throw an exception instead?? -- L.A. 4.6.2 */ + return generateIdentifierAsRandomString(datafile, prepend); } } - /* - * This method checks locally for a DvObject with the same PID and if that is OK, checks with the PID service. - * @param dvo - the object to check (ToDo - get protocol/authority from this PidProvider object) - * @param prepend - for Datasets, this is always the shoulder, for DataFiles, it could be the shoulder or the parent Dataset identifier + * This method checks locally for a DvObject with the same PID and if that is + * OK, checks with the PID service. + * + * @param dvo - the object to check (ToDo - get protocol/authority from this + * PidProvider object) + * + * @param prepend - for Datasets, this is always the shoulder, for DataFiles, it + * could be the shoulder or the parent Dataset identifier */ private String generateIdentifierAsRandomString(DvObject dvo, String prepend) { String identifier = null; do { identifier = prepend + RandomStringUtils.randomAlphanumeric(6).toUpperCase(); - } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); + } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), + this.getUrlPrefix(), this.getId()))); return identifier; } /* - * This method checks locally for a DvObject with the same PID and if that is OK, checks with the PID service. - * @param dvo - the object to check (ToDo - get protocol/authority from this PidProvider object) - * @param prepend - for Datasets, this is always the shoulder, for DataFiles, it could be the shoulder or the parent Dataset identifier + * This method checks locally for a DvObject with the same PID and if that is + * OK, checks with the PID service. + * + * @param dvo - the object to check (ToDo - get protocol/authority from this + * PidProvider object) + * + * @param prepend - for Datasets, this is always the shoulder, for DataFiles, it + * could be the shoulder or the parent Dataset identifier */ private String generateIdentifierFromStoredProcedureIndependent(DvObject dvo, String prepend) { - String identifier; + String identifier; do { String identifierFromStoredProcedure = pidProviderService.generateNewIdentifierByStoredProcedure(); - // some diagnostics here maybe - is it possible to determine that it's failing + // some diagnostics here maybe - is it possible to determine that it's failing // because the stored procedure hasn't been created in the database? if (identifierFromStoredProcedure == null) { - return null; + return null; } identifier = prepend + identifierFromStoredProcedure; - } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); - + } while (!isGlobalIdUnique(new GlobalId(dvo.getProtocol(), dvo.getAuthority(), identifier, this.getSeparator(), + this.getUrlPrefix(), this.getId()))); + return identifier; } - - /*This method is only used for DataFiles with DEPENDENT Pids. It is not for Datasets + + /* + * This method is only used for DataFiles with DEPENDENT Pids. It is not for + * Datasets * */ private String generateIdentifierFromStoredProcedureDependent(DataFile datafile, String prepend) { String identifier; Long retVal; retVal = Long.valueOf(0L); - //ToDo - replace loops with one lookup for largest entry? (the do loop runs ~n**2/2 calls). The check for existingIdentifiers means this is mostly a local loop now, versus involving db or PidProvider calls, but still...) - + // ToDo - replace loops with one lookup for largest entry? (the do loop runs + // ~n**2/2 calls). The check for existingIdentifiers means this is mostly a + // local loop now, versus involving db or PidProvider calls, but still...) + // This will catch identifiers already assigned in the current transaction (e.g. // in FinalizeDatasetPublicationCommand) that haven't been committed to the db // without having to make a call to the PIDProvider Set existingIdentifiers = new HashSet(); List files = datafile.getOwner().getFiles(); - for(DataFile f:files) { + for (DataFile f : files) { existingIdentifiers.add(f.getIdentifier()); } - + do { retVal++; identifier = prepend + retVal.toString(); - } while (existingIdentifiers.contains(identifier) || !isGlobalIdUnique(new GlobalId(datafile.getProtocol(), datafile.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); + } while (existingIdentifiers.contains(identifier) || !isGlobalIdUnique(new GlobalId(datafile.getProtocol(), + datafile.getAuthority(), identifier, this.getSeparator(), this.getUrlPrefix(), this.getId()))); return identifier; } - public class GlobalIdMetadataTemplate { - - private String template; - - public GlobalIdMetadataTemplate(){ - try (InputStream in = GlobalIdMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { - template = new String(in.readAllBytes(),StandardCharsets.UTF_8); - } catch (Exception e) { - logger.log(Level.SEVERE, "datacite metadata template load error"); - logger.log(Level.SEVERE, "String " + e.toString()); - logger.log(Level.SEVERE, "localized message " + e.getLocalizedMessage()); - logger.log(Level.SEVERE, "cause " + e.getCause()); - logger.log(Level.SEVERE, "message " + e.getMessage()); + private String template; + + public GlobalIdMetadataTemplate() { + try (InputStream in = GlobalIdMetadataTemplate.class + .getResourceAsStream("datacite_metadata_template.xml")) { + template = new String(in.readAllBytes(), StandardCharsets.UTF_8); + } catch (Exception e) { + logger.log(Level.SEVERE, "datacite metadata template load error"); + logger.log(Level.SEVERE, "String " + e.toString()); + logger.log(Level.SEVERE, "localized message " + e.getLocalizedMessage()); + logger.log(Level.SEVERE, "cause " + e.getCause()); + logger.log(Level.SEVERE, "message " + e.getMessage()); + } } - } - - private String xmlMetadata; - private String identifier; - private List datafileIdentifiers; - private List creators; - private String title; - private String publisher; - private String publisherYear; - private List authors; - private String description; - private List contacts; - private List producers; - - public List getProducers() { - return producers; - } - - public void setProducers(List producers) { - this.producers = producers; - } - - public List getContacts() { - return contacts; - } - public void setContacts(List contacts) { - this.contacts = contacts; - } + private String xmlMetadata; + private String identifier; + private List datafileIdentifiers; + private List creators; + private String title; + private String publisher; + private String publisherYear; + private List authors; + private String description; + private List contacts; + private List producers; - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } + public List getProducers() { + return producers; + } + public void setProducers(List producers) { + this.producers = producers; + } - public List getDatafileIdentifiers() { - return datafileIdentifiers; - } + public List getContacts() { + return contacts; + } - public void setDatafileIdentifiers(List datafileIdentifiers) { - this.datafileIdentifiers = datafileIdentifiers; - } + public void setContacts(List contacts) { + this.contacts = contacts; + } - public GlobalIdMetadataTemplate(String xmlMetaData) { - this.xmlMetadata = xmlMetaData; - Document doc = Jsoup.parseBodyFragment(xmlMetaData); - Elements identifierElements = doc.select("identifier"); - if (identifierElements.size() > 0) { - identifier = identifierElements.get(0).html(); + public String getDescription() { + return description; } - Elements creatorElements = doc.select("creatorName"); - creators = new ArrayList<>(); - for (Element creatorElement : creatorElements) { - creators.add(creatorElement.html()); + + public void setDescription(String description) { + this.description = description; } - Elements titleElements = doc.select("title"); - if (titleElements.size() > 0) { - title = titleElements.get(0).html(); + + public List getAuthors() { + return authors; } - Elements publisherElements = doc.select("publisher"); - if (publisherElements.size() > 0) { - publisher = publisherElements.get(0).html(); + + public void setAuthors(List authors) { + this.authors = authors; } - Elements publisherYearElements = doc.select("publicationYear"); - if (publisherYearElements.size() > 0) { - publisherYear = publisherYearElements.get(0).html(); + + public List getDatafileIdentifiers() { + return datafileIdentifiers; } - } - public String generateXML(DvObject dvObject) { - // Can't use "UNKNOWN" here because DataCite will respond with "[facet 'pattern'] the value 'unknown' is not accepted by the pattern '[\d]{4}'" - String publisherYearFinal = "9999"; - // FIXME: Investigate why this.publisherYear is sometimes null now that pull request #4606 has been merged. - if (this.publisherYear != null) { - // Added to prevent a NullPointerException when trying to destroy datasets when using DataCite rather than EZID. - publisherYearFinal = this.publisherYear; + public void setDatafileIdentifiers(List datafileIdentifiers) { + this.datafileIdentifiers = datafileIdentifiers; } - xmlMetadata = template.replace("${identifier}", getIdentifier().trim()) - .replace("${title}", this.title) - .replace("${publisher}", this.publisher) - .replace("${publisherYear}", publisherYearFinal) - .replace("${description}", this.description); - StringBuilder creatorsElement = new StringBuilder(); - for (DatasetAuthor author : authors) { - creatorsElement.append(""); - creatorsElement.append(author.getName().getDisplayValue()); - creatorsElement.append(""); - if (author.getIdType() != null && author.getIdValue() != null && !author.getIdType().isEmpty() && !author.getIdValue().isEmpty() && author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { + public GlobalIdMetadataTemplate(String xmlMetaData) { + this.xmlMetadata = xmlMetaData; + Document doc = Jsoup.parseBodyFragment(xmlMetaData); + Elements identifierElements = doc.select("identifier"); + if (identifierElements.size() > 0) { + identifier = identifierElements.get(0).html(); + } + Elements creatorElements = doc.select("creatorName"); + creators = new ArrayList<>(); + for (Element creatorElement : creatorElements) { + creators.add(creatorElement.html()); + } + Elements titleElements = doc.select("title"); + if (titleElements.size() > 0) { + title = titleElements.get(0).html(); + } + Elements publisherElements = doc.select("publisher"); + if (publisherElements.size() > 0) { + publisher = publisherElements.get(0).html(); + } + Elements publisherYearElements = doc.select("publicationYear"); + if (publisherYearElements.size() > 0) { + publisherYear = publisherYearElements.get(0).html(); + } + } - if (author.getIdType().equals("ORCID")) { - creatorsElement.append("" + author.getIdValue() + ""); - } - if (author.getIdType().equals("ISNI")) { - creatorsElement.append("" + author.getIdValue() + ""); + public String generateXML(DvObject dvObject) { + // Can't use "UNKNOWN" here because DataCite will respond with "[facet + // 'pattern'] the value 'unknown' is not accepted by the pattern '[\d]{4}'" + String publisherYearFinal = "9999"; + // FIXME: Investigate why this.publisherYear is sometimes null now that pull + // request #4606 has been merged. + if (this.publisherYear != null) { + // Added to prevent a NullPointerException when trying to destroy datasets when + // using DataCite rather than EZID. + publisherYearFinal = this.publisherYear; + } + xmlMetadata = template.replace("${identifier}", getIdentifier().trim()).replace("${title}", this.title) + .replace("${publisher}", this.publisher).replace("${publisherYear}", publisherYearFinal) + .replace("${description}", this.description); + StringBuilder creatorsElement = new StringBuilder(); + for (DatasetAuthor author : authors) { + creatorsElement.append(""); + creatorsElement.append(author.getName().getDisplayValue()); + creatorsElement.append(""); + + if (author.getIdType() != null && author.getIdValue() != null && !author.getIdType().isEmpty() + && !author.getIdValue().isEmpty() && author.getAffiliation() != null + && !author.getAffiliation().getDisplayValue().isEmpty()) { + + if (author.getIdType().equals("ORCID")) { + creatorsElement.append( + "" + + author.getIdValue() + ""); + } + if (author.getIdType().equals("ISNI")) { + creatorsElement.append( + "" + + author.getIdValue() + ""); + } + if (author.getIdType().equals("LCNA")) { + creatorsElement.append( + "" + + author.getIdValue() + ""); + } } - if (author.getIdType().equals("LCNA")) { - creatorsElement.append("" + author.getIdValue() + ""); + if (author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { + creatorsElement + .append("" + author.getAffiliation().getDisplayValue() + ""); } + creatorsElement.append(""); } - if (author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { - creatorsElement.append("" + author.getAffiliation().getDisplayValue() + ""); + xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); + + StringBuilder contributorsElement = new StringBuilder(); + for (String[] contact : this.getContacts()) { + if (!contact[0].isEmpty()) { + contributorsElement.append("" + + contact[0] + ""); + if (!contact[1].isEmpty()) { + contributorsElement.append("" + contact[1] + ""); + } + contributorsElement.append(""); + } } - creatorsElement.append(""); - } - xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); - - StringBuilder contributorsElement = new StringBuilder(); - for (String[] contact : this.getContacts()) { - if (!contact[0].isEmpty()) { - contributorsElement.append("" + contact[0] + ""); - if (!contact[1].isEmpty()) { - contributorsElement.append("" + contact[1] + ""); + for (String[] producer : this.getProducers()) { + contributorsElement.append("" + producer[0] + + ""); + if (!producer[1].isEmpty()) { + contributorsElement.append("" + producer[1] + ""); } contributorsElement.append(""); } - } - for (String[] producer : this.getProducers()) { - contributorsElement.append("" + producer[0] + ""); - if (!producer[1].isEmpty()) { - contributorsElement.append("" + producer[1] + ""); - } - contributorsElement.append(""); - } - String relIdentifiers = generateRelatedIdentifiers(dvObject); + String relIdentifiers = generateRelatedIdentifiers(dvObject); - xmlMetadata = xmlMetadata.replace("${relatedIdentifiers}", relIdentifiers); + xmlMetadata = xmlMetadata.replace("${relatedIdentifiers}", relIdentifiers); - xmlMetadata = xmlMetadata.replace("{$contributors}", contributorsElement.toString()); - return xmlMetadata; - } + xmlMetadata = xmlMetadata.replace("{$contributors}", contributorsElement.toString()); + return xmlMetadata; + } - private String generateRelatedIdentifiers(DvObject dvObject) { + private String generateRelatedIdentifiers(DvObject dvObject) { - StringBuilder sb = new StringBuilder(); - if (dvObject.isInstanceofDataset()) { - Dataset dataset = (Dataset) dvObject; - if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { - - datafileIdentifiers = new ArrayList<>(); - for (DataFile dataFile : dataset.getFiles()) { - if (!dataFile.getGlobalId().asString().isEmpty()) { - if (sb.toString().isEmpty()) { - sb.append(""); + StringBuilder sb = new StringBuilder(); + if (dvObject.isInstanceofDataset()) { + Dataset dataset = (Dataset) dvObject; + if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { + + datafileIdentifiers = new ArrayList<>(); + for (DataFile dataFile : dataset.getFiles()) { + if (!dataFile.getGlobalId().asString().isEmpty()) { + if (sb.toString().isEmpty()) { + sb.append(""); + } + sb.append("" + + dataFile.getGlobalId() + ""); } - sb.append("" + dataFile.getGlobalId() + ""); } - } - if (!sb.toString().isEmpty()) { - sb.append(""); + if (!sb.toString().isEmpty()) { + sb.append(""); + } } + } else if (dvObject.isInstanceofDataFile()) { + DataFile df = (DataFile) dvObject; + sb.append(""); + sb.append("" + + df.getOwner().getGlobalId() + ""); + sb.append(""); } - } else if (dvObject.isInstanceofDataFile()) { - DataFile df = (DataFile) dvObject; - sb.append(""); - sb.append("" + df.getOwner().getGlobalId() + ""); - sb.append(""); + return sb.toString(); } - return sb.toString(); - } - public void generateFileIdentifiers(DvObject dvObject) { + public void generateFileIdentifiers(DvObject dvObject) { - if (dvObject.isInstanceofDataset()) { - Dataset dataset = (Dataset) dvObject; + if (dvObject.isInstanceofDataset()) { + Dataset dataset = (Dataset) dvObject; - if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { + if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { - datafileIdentifiers = new ArrayList<>(); - for (DataFile dataFile : dataset.getFiles()) { - datafileIdentifiers.add(dataFile.getIdentifier()); - int x = xmlMetadata.indexOf("") - 1; - xmlMetadata = xmlMetadata.replace("{relatedIdentifier}", dataFile.getIdentifier()); - xmlMetadata = xmlMetadata.substring(0, x) + "${relatedIdentifier}" + template.substring(x, template.length() - 1); + datafileIdentifiers = new ArrayList<>(); + for (DataFile dataFile : dataset.getFiles()) { + datafileIdentifiers.add(dataFile.getIdentifier()); + int x = xmlMetadata.indexOf("") - 1; + xmlMetadata = xmlMetadata.replace("{relatedIdentifier}", dataFile.getIdentifier()); + xmlMetadata = xmlMetadata.substring(0, x) + + "${relatedIdentifier}" + + template.substring(x, template.length() - 1); - } + } - } else { - xmlMetadata = xmlMetadata.replace("${relatedIdentifier}", ""); + } else { + xmlMetadata = xmlMetadata.replace( + "${relatedIdentifier}", + ""); + } } } - } - public String getTemplate() { - return template; - } + public String getTemplate() { + return template; + } - public void setTemplate(String templateIn) { - template = templateIn; - } + public void setTemplate(String templateIn) { + template = templateIn; + } - public String getIdentifier() { - return identifier; - } + public String getIdentifier() { + return identifier; + } - public void setIdentifier(String identifier) { - this.identifier = identifier; - } + public void setIdentifier(String identifier) { + this.identifier = identifier; + } - public List getCreators() { - return creators; - } + public List getCreators() { + return creators; + } - public void setCreators(List creators) { - this.creators = creators; - } + public void setCreators(List creators) { + this.creators = creators; + } - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } - public void setTitle(String title) { - this.title = title; - } + public void setTitle(String title) { + this.title = title; + } - public String getPublisher() { - return publisher; - } + public String getPublisher() { + return publisher; + } - public void setPublisher(String publisher) { - this.publisher = publisher; - } + public void setPublisher(String publisher) { + this.publisher = publisher; + } - public String getPublisherYear() { - return publisherYear; - } + public String getPublisherYear() { + return publisherYear; + } - public void setPublisherYear(String publisherYear) { - this.publisherYear = publisherYear; + public void setPublisherYear(String publisherYear) { + this.publisherYear = publisherYear; + } } -} + public String getMetadataFromDvObject(String identifier, Map metadata, DvObject dvObject) { Dataset dataset = null; @@ -731,7 +763,7 @@ public String getMetadataFromDvObject(String identifier, Map met metadataTemplate.setProducers(dataset.getLatestVersion().getDatasetProducers()); metadataTemplate.setTitle(dvObject.getCurrentName()); String producerString = pidProviderService.getProducer(); - if (producerString.isEmpty() || producerString.equals(DatasetField.NA_VALUE) ) { + if (producerString.isEmpty() || producerString.equals(DatasetField.NA_VALUE)) { producerString = UNAVAILABLE; } metadataTemplate.setPublisher(producerString); @@ -744,15 +776,16 @@ public String getMetadataFromDvObject(String identifier, Map met @Override public boolean canManagePID() { - //The default expectation is that PID providers are configured to manage some set (i.e. based on protocol/authority/shoulder) of PIDs + // The default expectation is that PID providers are configured to manage some + // set (i.e. based on protocol/authority/shoulder) of PIDs return true; } - + @Override public void setPidProviderServiceBean(PidProviderFactoryBean pidProviderServiceBean) { this.pidProviderService = pidProviderServiceBean; } - + @Override public String getProtocol() { return protocol; @@ -797,7 +830,7 @@ public String getId() { public String getLabel() { return label; } - + @Override /** * True if this provider can manage PIDs in general, this pid is not in the @@ -807,8 +840,9 @@ public String getLabel() { * clause covers the potential case where the effective pid provider/generator * for the dataset is set to a different one that handles the dataset's pid * itself. In this case, we can create file PIDs if they are independent. + * * @param pid - the related pid to check - * @return true if this provider can manage PIDs like the one supplied + * @return true if this provider can manage PIDs like the one supplied */ public boolean canCreatePidsLike(GlobalId pid) { return canManagePID() && !managedSet.contains(pid.asString()) From 67862e67e67a30f0114723945ef6fc74d8017c1f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 15:15:23 -0500 Subject: [PATCH 055/113] fix test - don't reset list of providers --- .../harvard/iq/dataverse/pidproviders/PidUtilTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 5b2bac105de..3e2fedb5ff2 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -385,17 +385,17 @@ public void testLegacyConfig() throws IOException { Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Shoulder)).thenReturn("FK2"); Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol)).thenReturn("doi"); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("10.5072"); + Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("10.5075"); String protocol = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol); String authority = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority); String shoulder = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Shoulder); String provider = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider); - PidUtil.clearPidProviders(); if (protocol != null && authority != null && shoulder != null && provider != null) { - System.out.println("Looking"); - if (PidUtil.getPidProvider(protocol, authority, shoulder) == null) { + // This line is different than in PidProviderFactoryBean because here we've + // already added the unmanaged providers, so we can't look for null + if (!PidUtil.getPidProvider(protocol, authority, shoulder).canManagePID()) { // Try to add a legacy provider String identifierGenerationStyle = settingsServiceBean .getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "random"); @@ -435,7 +435,7 @@ public void testLegacyConfig() throws IOException { } - String pid1String = "doi:10.5072/FK2ABCDEF"; + String pid1String = "doi:10.5075/FK2ABCDEF"; GlobalId pid2 = PidUtil.parseAsGlobalID(pid1String); assertEquals(pid1String, pid2.asString()); assertEquals("legacy", pid2.getProviderId()); From 1a58684bf4cd64cb0c5c91875221479c6977a9df Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 16:14:19 -0500 Subject: [PATCH 056/113] allow old aliases --- .../edu/harvard/iq/dataverse/settings/JvmSettings.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index fcc1a2bc963..816a6607824 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -106,10 +106,10 @@ public enum JvmSettings { // PROVIDER DATACITE (legacy - single provider setting) SCOPE_LEGACY_PID_DATACITE(SCOPE_PID, "datacite"), - LEGACY_DATACITE_MDS_API_URL(SCOPE_LEGACY_PID_DATACITE, "mds-api-url"), - LEGACY_DATACITE_REST_API_URL(SCOPE_LEGACY_PID_DATACITE, "rest-api-url"), - LEGACY_DATACITE_USERNAME(SCOPE_LEGACY_PID_DATACITE, "username"), - LEGACY_DATACITE_PASSWORD(SCOPE_LEGACY_PID_DATACITE, "password"), + LEGACY_DATACITE_MDS_API_URL(SCOPE_LEGACY_PID_DATACITE, "mds-api-url", "doi.baseurlstring"), + LEGACY_DATACITE_REST_API_URL(SCOPE_LEGACY_PID_DATACITE, "rest-api-url", "doi.dataciterestapiurlstring", "doi.mdcbaseurlstring"), + LEGACY_DATACITE_USERNAME(SCOPE_LEGACY_PID_DATACITE, "username", "doi.username"), + LEGACY_DATACITE_PASSWORD(SCOPE_LEGACY_PID_DATACITE, "password", "doi.password"), // PROVIDER EZID - these settings were formerly kept together with DataCite ones SCOPE_PID_EZID(SCOPE_PID_PROVIDER, "ezid"), From 42931832dbbce39387e9a1153de8882ee58ec877 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 16:53:07 -0500 Subject: [PATCH 057/113] reverse logic in datacite legacy creator, add null check --- .../pidproviders/PidProviderFactoryBean.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index fd6d7909623..c52316b2ba9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -152,9 +152,10 @@ private void loadProviders() { case "DataCite": String mdsUrl = JvmSettings.LEGACY_DATACITE_MDS_API_URL.lookup(String.class); String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(String.class); - String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class); - String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class); - if (mdsUrl == null || restUrl == null || dcUsername == null || dcPassword == null) { + //Defaults for testing where no account is set up + String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class,""); + String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class,""); + if (mdsUrl != null && restUrl != null && dcUsername != null && dcPassword != null) { legacy = new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, dcPassword); @@ -166,8 +167,10 @@ private void loadProviders() { identifierGenerationStyle, dataFilePidFormat, "", ""); break; } - legacy.setPidProviderServiceBean(this); - PidUtil.addToProviderList(legacy); + if (legacy != null) { + legacy.setPidProviderServiceBean(this); + PidUtil.addToProviderList(legacy); + } } else { logger.warning("Legacy PID provider settings found - ignored since a provider for the same protocol, authority, shoulder has been registered"); } From 61036229845fb977e1d71b68b0ad112caf600471 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 12 Jan 2024 17:18:51 -0500 Subject: [PATCH 058/113] fix lookups, update test, test DataCite legacy --- .../pidproviders/PidProviderFactoryBean.java | 4 +-- .../dataverse/pidproviders/PidUtilTest.java | 28 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index c52316b2ba9..2b3190f738f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -153,8 +153,8 @@ private void loadProviders() { String mdsUrl = JvmSettings.LEGACY_DATACITE_MDS_API_URL.lookup(String.class); String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(String.class); //Defaults for testing where no account is set up - String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class,""); - String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class,""); + String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class); + String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class); if (mdsUrl != null && restUrl != null && dcUsername != null && dcPassword != null) { legacy = new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 3e2fedb5ff2..52706378438 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -379,14 +379,20 @@ public void testFindingPidGenerators() throws IOException { } @Test + @JvmSetting(key = JvmSettings.LEGACY_DATACITE_MDS_API_URL, value = "https://mds.test.datacite.org/") + @JvmSetting(key = JvmSettings.LEGACY_DATACITE_REST_API_URL, value = "https://api.test.datacite.org") + @JvmSetting(key = JvmSettings.LEGACY_DATACITE_USERNAME, value = "test2") + @JvmSetting(key = JvmSettings.LEGACY_DATACITE_PASSWORD, value = "changeme2") public void testLegacyConfig() throws IOException { MockitoAnnotations.openMocks(this); - Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider)).thenReturn("FAKE"); + Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.DoiProvider)).thenReturn("DataCite"); Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Shoulder)).thenReturn("FK2"); Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol)).thenReturn("doi"); Mockito.when(settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority)).thenReturn("10.5075"); + + String protocol = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Protocol); String authority = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Authority); String shoulder = settingsServiceBean.getValueForKey(SettingsServiceBean.Key.Shoulder); @@ -396,6 +402,7 @@ public void testLegacyConfig() throws IOException { // This line is different than in PidProviderFactoryBean because here we've // already added the unmanaged providers, so we can't look for null if (!PidUtil.getPidProvider(protocol, authority, shoulder).canManagePID()) { + PidProvider legacy = null; // Try to add a legacy provider String identifierGenerationStyle = settingsServiceBean .getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "random"); @@ -407,9 +414,9 @@ public void testLegacyConfig() throws IOException { * String baseUrl = JvmSettings.PID_EZID_BASE_URL.lookup(String.class); String * username = JvmSettings.PID_EZID_USERNAME.lookup(String.class); String * password = JvmSettings.PID_EZID_PASSWORD.lookup(String.class); - * PidUtil.addToProviderList( new EZIdDOIProvider("legacy", "legacy", authority, + * legacy = new EZIdDOIProvider("legacy", "legacy", authority, * shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", baseUrl, - * username, password)); + * username, password); */ break; case "DataCite": @@ -417,18 +424,23 @@ public void testLegacyConfig() throws IOException { String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(String.class); String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class); String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class); - if (mdsUrl == null || restUrl == null || dcUsername == null || dcPassword == null) { - PidUtil.addToProviderList(new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, + if (mdsUrl != null && restUrl != null && dcUsername != null && dcPassword != null) { + legacy = new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, - dcPassword)); + dcPassword); } break; case "FAKE": System.out.println("Legacy FAKE found"); - PidUtil.addToProviderList(new FakeDOIProvider("legacy", "legacy", authority, shoulder, - identifierGenerationStyle, dataFilePidFormat, "", "")); + legacy = new FakeDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", ""); break; } + if (legacy != null) { + // Not testing parts that require this bean + legacy.setPidProviderServiceBean(null); + PidUtil.addToProviderList(legacy); + } } else { System.out.println("Legacy PID provider settings found - ignored since a provider for the same protocol, authority, shoulder has been registered"); } From 694aad4837bf036622abf871cc6ea7fffbb0f8f2 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Sat, 13 Jan 2024 17:34:06 -0500 Subject: [PATCH 059/113] missing if! --- .../dataverse/pidproviders/AbstractPidProvider.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index b2c69b72aaa..40063907c78 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -197,11 +197,12 @@ public DvObject generatePid(DvObject dvObject) { if (dvObject.getAuthority() == null) { dvObject.setAuthority(getAuthority()); } else { - logger.warning("The authority of the DvObject (" + dvObject.getAuthority() - + ") does not match the configured authority (" + getAuthority() + ")"); - throw new IllegalArgumentException("The authority of the DvObject (" + dvObject.getAuthority() - + ") doesn't match that of the provider, id: " + getId()); - + if (!dvObject.getAuthority().equals(getAuthority())) { + logger.warning("The authority of the DvObject (" + dvObject.getAuthority() + + ") does not match the configured authority (" + getAuthority() + ")"); + throw new IllegalArgumentException("The authority of the DvObject (" + dvObject.getAuthority() + + ") doesn't match that of the provider, id: " + getId()); + } } if (dvObject.isInstanceofDataset()) { dvObject.setIdentifier(generateDatasetIdentifier((Dataset) dvObject)); From 67ce7c8d2ba0896212fe0a8e9db033fe6061a3f6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Sat, 13 Jan 2024 20:58:19 -0500 Subject: [PATCH 060/113] disable obsolete test --- src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java index 5753550d564..c1828279266 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -1022,6 +1022,10 @@ public void testExcludeEmail() { } + @Disabled + /*The identifier generation style is no longer a global, dynamically changeable setting. To make this test work after PR #10234, + * will require configuring a PidProvider that uses this style and creating a collection/dataset that uses that provider. + */ @Test public void testStoredProcGeneratedAsIdentifierGenerationStyle() { // Please note that this test only works if the stored procedure From 127aab43a64917101d8d2cbe76439f2385caf5c3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 18 Jan 2024 18:01:34 -0500 Subject: [PATCH 061/113] updated docs --- doc/release-notes/3623-multipid.md | 37 ++ .../source/installation/config.rst | 448 +++++++++++++++--- 2 files changed, 420 insertions(+), 65 deletions(-) create mode 100644 doc/release-notes/3623-multipid.md diff --git a/doc/release-notes/3623-multipid.md b/doc/release-notes/3623-multipid.md new file mode 100644 index 00000000000..abeb96dd477 --- /dev/null +++ b/doc/release-notes/3623-multipid.md @@ -0,0 +1,37 @@ +This release adds support for using multiple PID (DOI, Handle, PermalLink) providers, multiple PID provider accounts +(managing a given protocol, authority,separator, shoulder combination), assigning PID provider accounts to specific collections, +and supporting transferred PIDs (where a PID is managed by an account when it's authority, separator, and/or shoulder don't match +the combination where the account can mint new PIDs). It also adds the ability for additional provider services beyond the existing +DataCite, EZId, Handle, and PermaLink providers to be dynamically added as separate jar files. + +These changes require per-provider settings rather than the global PID settings previously supported. While backward compatibility +for installations using a single PID Provider account is provided, updating to use the new microprofile settings is highly recommended. + +New microprofile settings (where * indicates a provider id indicating which provider the setting is for): + +dataverse.pid.providers +dataverse.pid.default-provider +dataverse.pid.provider-implementations-directory +dataverse.pid.*.type +dataverse.pid.*.label +dataverse.pid.*.authority +dataverse.pid.*.shoulder +dataverse.pid.*.identifier-generation-style +dataverse.pid.*.datafile-pid-format +dataverse.pid.*.managed-list +dataverse.pid.*.excluded-list +dataverse.pid.*.datacite.mds-api-url +dataverse.pid.*.datacite.rest-api-url +dataverse.pid.*.datacite.username +dataverse.pid.*.datacite.password +dataverse.pid.*.ezid.api-url +dataverse.pid.*.ezid.username +dataverse.pid.*.ezid.password +dataverse.pid.*.permalink.base-url +dataverse.pid.*.permalink.separator +dataverse.pid.*.handlenet.index +dataverse.pid.*.handlenet.independent-service +dataverse.pid.*.handlenet.auth-handle +dataverse.pid.*.handlenet.key.path +dataverse.pid.*.handlenet.key.passphrase + diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index a7d7905ca4a..9a6a9def1d1 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -178,38 +178,40 @@ Persistent Identifiers and Publishing Datasets Persistent identifiers (PIDs) are a required and integral part of the Dataverse Software. They provide a URL that is guaranteed to resolve to the datasets or files they represent. The Dataverse Software currently supports creating -identifiers using one of several PID providers. The most appropriate PIDs for public data are DOIs (provided by +identifiers using any of several PID types. The most appropriate PIDs for public data are DOIs (e.g., provided by DataCite or EZID) and Handles. Dataverse also supports PermaLinks which could be useful for intranet or catalog use cases. A DOI provider called "FAKE" is recommended only for testing and development purposes. +Dataverse can be configured with one or more PID providers, each of which can mint and manage PIDs with a given protocol +(e.g., doi, handle, permalink) using a specific service provider/account (e.g. with DataCite, EZId, or HandleNet) +to manage an authority/shoulder combination, aka a "prefix" (PermaLinks also support custom separator characters as part of the prefix), +along with an optional list of individual PIDs (with different authority/shoulders) than can be managed with that account. + Testing PID Providers +++++++++++++++++++++ By default, the installer configures the DataCite test service as the registration provider. DataCite requires that you -register for a test account, configured with your own prefix (please contact support@datacite.org). +register for a test account, configured with your own prefix (please contact support@datacite.org for a test account. Alternately, +you may wish to `contact the GDCC `_ - GDCC is able to provide DataCite accounts with a group discount and can also provide test accounts.). Once you receive the login name, password, and prefix for the account, -configure the credentials via :ref:`dataverse.pid.datacite.username` and -:ref:`dataverse.pid.datacite.password`, then restart Payara. - -Configure the prefix via the API (where it is referred to as :ref:`:Authority`): +configure the credentials as described below. -``curl -X PUT -d 10.xxxx http://localhost:8080/api/admin/settings/:Authority`` +Alternately, you may wish to configure other providers for testing: -.. TIP:: - This testing section is oriented around DataCite but other PID Providers can be tested as well. - - EZID is available to University of California scholars and researchers. Testing can be done using the authority 10.5072 and shoulder FK2 with the "apitest" account (contact EZID for credentials) or an institutional account. Configuration in Dataverse is then analogous to using DataCite. - - The PermaLink and FAKE DOI providers do not involve an external account. See :ref:`permalinks` and (for the FAKE DOI provider) the :doc:`/developers/dev-environment` section of the Developer Guide. + - The PermaLink and FAKE DOI providers do not involve an external account. The FAKE provider should only be used for testing, since it creates identifiers that look like DOIs but will not resolve. In contrast, the PermaLink provider creates PIDs that begin with "perma:", making it clearer that they are not DOIs, while they do resolve to the local dataset/file page in Dataverse. See :ref:`permalinks` and (for the FAKE DOI provider) the :doc:`/developers/dev-environment` section of the Developer Guide. + +Provider-specific configuration is described below. Once all is configured, you will be able to publish datasets and files, but **the persistent identifiers will not be citable**, -and they will only resolve from the DataCite test environment (and then only if the Dataverse installation from which +e.g. they will only resolve from the DataCite test environment (and then only if the Dataverse installation from which you published them is accessible - DOIs minted from your laptop will not resolve). Note that any datasets or files created using the test configuration cannot be directly migrated and would need to be created again once a valid DOI namespace is configured. -One you are done testing, to properly configure persistent identifiers for a production installation, an account and associated namespace must be +One you are done testing, to properly configure persistent identifiers for a production installation, an account and associated namespace (e.g. authority/shoulder) must be acquired for a fee from a DOI or HDL provider. **DataCite** (https://www.datacite.org) is the recommended DOI provider (see https://dataversecommunity.global for more on joining DataCite through the Global Dataverse Community Consortium) but **EZID** (http://ezid.cdlib.org) is an option for the University of California according to @@ -217,17 +219,337 @@ https://www.cdlib.org/cdlinfo/2017/08/04/ezid-doi-service-is-evolving/ . **Handle.Net** (https://www.handle.net) is the HDL provider. Once you have your DOI or Handle account credentials and a namespace, configure your Dataverse installation -using the JVM options and database settings below. +using the settings below. + + +Configuring PID Providers ++++++++++++++++++++++++++ + +There are two required global settings to configure PID providers - the list of ids of providers and which one of those should be the default. +Per-provider settings are also required - some that are common to all types and some type specific. All of these settings are defined +to be compatible with the MicroProfile specification which means that + +1. Any of these settings can be set via system properties (see :ref:`jvm-options` for how to do this), environment variables, or other + MicroProfile Config mechanisms supported by the app server. + `See Payara docs for supported sources `_. +2. Remember to protect your secrets. For passwords, use an environment variable (bare minimum), a password alias named the same + as the key (OK) or use the `"dir config source" of Payara `_ (best). + + Alias creation example: + + .. code-block:: shell + + echo "AS_ADMIN_ALIASPASSWORD=changeme" > /tmp/p.txt + asadmin create-password-alias --passwordfile /tmp/p.txt dataverse.pid.datacite1.datacite.password + rm /tmp/p.txt + +3. Environment variables follow the key, replacing any dot, colon, dash, etc. into an underscore "_" and all uppercase + letters. Example: ``dataverse.pid.default-provider`` -> ``DATAVERSE_PID_DEFAULT_PROVIDER`` + +Global Settings +############### + +The following three global settings are required to configure PID Providers in the Dataverse software: + +.. _dataverse.pid.providers: + +dataverse.pid.providers +####################### + +A comma-separated list of the ids of the PID providers to use. IDs should be simple unique text strings, e.g. datacite1, perma1, etc. +IDs are used to scope the provider-specific settings but are not directly visible to users. + +.. _dataverse.pid.default-provider: + +dataverse.pid.default-provider +############################## + +The ID of the default PID provider to use. + +.. _dataverse.pid.provider-implementations-directory: + +dataverse.pid.provider-implementations-directory +################################################ + +The path to the directory where JAR files containing additional types of PID Providers can be added. +Dataverse includes providers that support DOIs (DataCite, EZId, or FAKE), Handles, and PermaLinks. +PID provider jar files added to this directory can replace any of these or add new PID Providers. + +Per-Provider Settings +##################### + +Each Provider listed by id in the dataverse.pid.providers setting must be configured with the following common settings and any settings that are specific to the provider type. + +.. _dataverse.pid.*.type: + +dataverse.pid.\*.type +#################### + +The Provider type, currently one of ``datacite``, ``ezid``, ``FAKE``, ``hdl``, or ``perma``. The type defines which protocol a service supports (DOI, Handle, or PermaLink) and, for DOI Providers, which +DOI service is used. + +.. _dataverse.pid.*.label: + +dataverse.pid.\*.label +###################### + +A human-readable label for the provider + +.. _dataverse.pid.*.authority: + +dataverse.pid.\*.authority +########################## + +.. _dataverse.pid.*.shoulder: + +dataverse.pid.\*.shoulder +######################### + +In general, PIDs are of the form ``:/*`` where ``*`` is the portion unique to an individual PID. PID Providers must define +the authority and shoulder (with the protocol defined by the ``dataverse.pid.*.type`` setting) that defines the set of existing PIDs they can manage and the prefix they can use when minting new PIDs. +(Often an account with a PID service provider will be limited to using a single authority/shoulder. If your PID service provider account allows more than one combination that you wish to use in Dataverse, configure multiple PID Provider, one for each combination.) + +.. _dataverse.pid.*.identifier-generation-style: + +dataverse.pid.\*.identifier-generation-style +############################################ + +By default, Pid Providers in Dataverse generate a random 6 character string, +pre-pended by the Shoulder if set, to use as the identifier for a Dataset. +Set this to ``storedProcGenerated`` to generate instead a custom *unique* +identifier (again pre-pended by the Shoulder if set) through a database +stored procedure or function (the assumed default setting is ``randomString``). +When using the ``storedProcGenerated`` setting, a stored procedure or function must be created in +the database. + +As a first example, the script below (downloadable +:download:`here `) produces +sequential numerical values. You may need to make some changes to suit your +system setup, see the comments for more information: + +.. literalinclude:: ../_static/util/createsequence.sql + :language: plpgsql + +As a second example, the script below (downloadable +:download:`here `) produces +sequential 8 character identifiers from a base36 representation of current +timestamp. + +.. literalinclude:: ../_static/util/identifier_from_timestamp.sql + :language: plpgsql + +Note that the SQL in these examples scripts is Postgres-specific. +If necessary, it can be reimplemented in any other SQL flavor - the standard +JPA code in the application simply expects the database to have a saved +function ("stored procedure") named ``generateIdentifierFromStoredProcedure()`` +returning a single ``varchar`` argument. + +Please note that this setting interacts with the ``dataverse.pid.*.datafile-pid-format`` +setting below to determine how datafile identifiers are generated. + + +.. _dataverse.pid.*.datafile-pid-format: + +dataverse.pid.\*.datafile-pid-format +#################################### + +This setting controls the way that the "identifier" component of a file's +persistent identifier (PID) relates to the PID of its "parent" dataset - for a give PID Provider. + +By default the identifier for a file is dependent on its parent dataset. +For example, if the identifier of a dataset is "TJCLKP", the identifier for +a file within that dataset will consist of the parent dataset's identifier +followed by a slash ("/"), followed by a random 6 character string, +yielding "TJCLKP/MLGWJO". Identifiers in this format are what you should +expect if you leave ``dataverse.pid.*.datafile-pid-format`` undefined or set it to +``DEPENDENT`` and have not changed the ``dataverse.pid.*.identifier-generation-style`` +setting from its default. + +Alternatively, the identifier for File PIDs can be configured to be +independent of Dataset PIDs using the setting ``INDEPENDENT``. +In this case, file PIDs will not contain the PIDs of their parent datasets, +and their PIDs will be generated the exact same way that datasets' PIDs are, +based on the ``dataverse.pid.*.identifier-generation-style`` setting described above +(random 6 character strings or custom unique identifiers through a stored +procedure, pre-pended by any shoulder). + +The chart below shows examples from each possible combination of parameters +from the two settings. ``dataverse.pid.*.identifier-generation-style`` can be either +``randomString`` (the default) or ``storedProcGenerated`` and +``dataverse.pid.*.datafile-pid-format`` can be either ``DEPENDENT`` (the default) or +``INDEPENDENT``. In the examples below the "identifier" for the dataset is +"TJCLKP" for ``randomString`` and "100001" for ``storedProcGenerated`` (when +using sequential numerical values, as described in +:ref:`dataverse.pid.*.identifier-generation-style` above), or "krby26qt" for +``storedProcGenerated`` (when using base36 timestamps, as described in +:ref:`dataverse.pid.*.identifier-generation-style` above). + ++-----------------+---------------+----------------------+---------------------+ +| | randomString | storedProcGenerated | storedProcGenerated | +| | | | | +| | | (sequential numbers) | (base36 timestamps) | ++=================+===============+======================+=====================+ +| **DEPENDENT** | TJCLKP/MLGWJO | 100001/1 | krby26qt/1 | ++-----------------+---------------+----------------------+---------------------+ +| **INDEPENDENT** | MLGWJO | 100002 | krby27pz | ++-----------------+---------------+----------------------+---------------------+ + +As seen above, in cases where ``dataverse.pid.*.identifier-generation-style`` is set to +``storedProcGenerated`` and ``dataverse.pid.*.datafile-pid-format`` is set to ``DEPENDENT``, +each file within a dataset will be assigned a number *within* that dataset +starting with "1". + +Otherwise, if ``dataverse.pid.*.datafile-pid-format`` is set to ``INDEPENDENT``, each file +within the dataset is assigned with a new PID which is the next available +identifier provided from the database stored procedure. In our example: +"100002" when using sequential numbers or "krby27pz" when using base36 +timestamps. + +.. _dataverse.pid.*.managed-list: + +dataverse.pid.\*.managed-list +############################# + +.. _dataverse.pid.*.excluded-list: + +dataverse.pid.\*.excluded-list +############################## + +With at least some PID services, it is possible for the authority(permission) to manage specific individual PIDs +to be transferred between accounts. To handle these cases, the individual PIDs, written in the +standard format, e.g. doi:10.5072/FK2ABCDEF can be added to the comma-separated ``managed`` or ``excluded`` list +for a given provider. For entries on the ``managed- list``, Dataverse will assume this PID +Provider/account can update the metadata and landing URL for the PID at the service provider +(even though it does not match the provider's authority/shoulder settings). Conversely, +Dataverse will assume that PIDs on the ``excluded-list`` cannot be managed/updated by this provider +(even though they match the provider's authority/shoulder settings). These settings are optional +with the default assumption that these lists are empty. + +.. _dataverse.pid.*.datacite: + +DataCite-specific Settings +########################## + +dataverse.pid.\*.datacite.mds-api-url +##################################### +dataverse.pid.\*.datacite.rest-api-url +###################################### +dataverse.pid.\*.datacite.username +################################## +dataverse.pid.\*.datacite.password +################################## + +PID Providers of type ``datacite`` require four additional parameters that define how the provider connects to DataCite. +DataCite has two APIs that are used in Dataverse: + +The base URL of the `DataCite MDS API `_, +used to mint and manage DOIs. Current valid values for ``dataverse.pid.*.datacite.mds-api-url`` are "https://mds.datacite.org" (production) and "https://mds.test.datacite.org" (testing, the default). + +The `DataCite REST API `_ is also used - :ref:`PIDs API ` information retrieval and :doc:`/admin/make-data-count`. +Current valid values for ``dataverse.pid.*.datacite.rest-api-url`` are "https://api.datacite.org" (production) and "https://api.test.datacite.org" (testing, the default). + +DataCite uses `HTTP Basic authentication `_ +for `Fabrica `_ 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. + + +.. _dataverse.pid.*.ezid: + +EZId-specific Settings +###################### + +dataverse.pid.\*.ezid.api-url +############################# +dataverse.pid.\*.ezid.username +############################## +dataverse.pid.\*.ezid.password +############################## + +Note that use of `EZId `_ is limited primarily to University of California institutions. If you have an EZId account, +you will need to configure the ``api-url`` and your account ``username`` and ``password``. As above, you should use one of the more secure +options for setting the password. + +.. _dataverse.pid.*.permalink: + +PermaLink-specific Settings +########################### + +dataverse.pid.\*.permalink.base-url +################################### + +dataverse.pid.\*.permalink.separator +#################################### + +PermaLinks are a simple PID option intended for intranet and catalog use cases. They can be used without an external service or +be configured with the ``base-url`` of a resolution service. PermaLinks also allow a custom ``separator`` to be used. (Note: when using multiple +PermaLink providers, you should avoid ambiguous authority/separator/shoulder combinations that would result in the same overall prefix.) + +.. _dataverse.pid.*.handlenet: + +Handle-specific Settings +######################## + +dataverse.pid.\*.handlenet.index +################################ + +dataverse.pid.\*.handlenet.independent-service +############################################## + +dataverse.pid.\*.handlenet.auth-handle +###################################### + +dataverse.pid.\*.handlenet.key +############################## + +dataverse.pid.\*.handlenet.path +############################### + +dataverse.pid.\*.handlenet.passphrase +##################################### + +Note: If you are **minting your own handles** and plan to set up your own handle service, please refer to `Handle.Net documentation `_. + +Configure your Handle.net ``index`` to be used registering new persistent +identifiers. Defaults to ``300``. + +Indices are used to separate concerns within the Handle system. To add data to +an index, authentication is mandatory. See also chapter 1.4 "Authentication" of +the `Handle.Net Technical Documentation `__ + +Handle.Net servers use a public key authentication method where the public key +is stored in a handle itself and the matching private key is provided from this +file. Typically, the absolute path ends like ``handle/svr_1/admpriv.bin``. +The key file may (and should) be encrypted with a passphrase (used for +encryption with AES-128). See +also chapter 1.4 "Authentication" of the `Handle.Net Technical Documentation +`__ + +Provide an absolute ``key.path`` to a private key file authenticating requests to your +Handle.Net server. + +Provide a ``key.passphrase`` to decrypt the private key file at ``dataverse.pid.*.handlenet.key.path``. + +Set ``independent-service`` to true if you want to use a Handle service which is setup to work 'independently' (No communication with the Global Handle Registry). +By default this setting is false. + +Set ``auth-handle`` to / to be used on a global handle service when the public key is NOT stored in the default handle. +This setting is optional. If the public key is, for instance, stored in handle: ``21.T12996/USER01``, ``auth-handle`` should be set to this value. + .. _pids-doi-configuration: -Configuring Your Dataverse Installation for DOIs -++++++++++++++++++++++++++++++++++++++++++++++++ +Backward-compatibility for Single PID Provider Installations +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +While using the PID Provider configuration settings described above is recommended, Dataverse installations +only using a single PID Provider can use the settings below instead. In general, these legacy settings mirror +those above except for not including a PID Provider id. -As explained above, by default your Dataverse installation attempts to register DOIs for each -dataset and file under a test authority. You must apply for your own credentials. +Configuring Your Dataverse Installation for a SIngle DOI Provider +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Here are the configuration options for DOIs: +Here are the configuration options for DOIs.: **JVM Options for DataCite:** @@ -257,8 +579,8 @@ this provider. .. _pids-handle-configuration: -Configuring Your Dataverse Installation for Handles -+++++++++++++++++++++++++++++++++++++++++++++++++++ +Configuring Your Dataverse Installation for a Single Handle Provider +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here are the configuration options for handles. Most notably, you need to change the ``:Protocol`` setting, as it defaults to DOI usage. @@ -282,12 +604,8 @@ Note: If you are **minting your own handles** and plan to set up your own handle .. _permalinks: -Configuring Your Dataverse Installation for PermaLinks -++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -PermaLinks are a simple mechanism to provide persistent URLs for datasets and datafiles (if configured) that does not involve an external service providing metadata-based search services. -They are potentially appropriate for Intranet use cases as well as in cases where Dataverse is being used as a catalog or holding duplicate copies of datasets where the authoritative copy already has a DOI or Handle. -PermaLinks use the protocol "perma" (versus "doi" or "handle") and do not use a "/" character as a separator between the authority and shoulder. It is recommended to choose an alphanumeric value for authority that does not resemble that of DOIs (which are primarily numeric and start with "10." as in "10.5072") to avoid PermaLinks being mistaken for DOIs. +Configuring Your Dataverse Installation for a Single PermaLink Provider +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here are the configuration options for PermaLinks: @@ -2114,8 +2432,8 @@ For limiting the size (in bytes) of thumbnail images generated from files. The d .. _dataverse.pid.datacite.mds-api-url: -dataverse.pid.datacite.mds-api-url -++++++++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.datacite.mds-api-url +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Configure the base URL of the `DataCite MDS API `_, used to mint and manage DOIs. Valid values are "https://mds.datacite.org" and "https://mds.test.datacite.org" @@ -2148,8 +2466,8 @@ Without setting an option, always defaults to testing API endpoint. .. _dataverse.pid.datacite.rest-api-url: -dataverse.pid.datacite.rest-api-url -+++++++++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.datacite.rest-api-url ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Configure the base URL endpoint of the `DataCite REST API `_, used for :ref:`PIDs API ` information retrieval and :doc:`/admin/make-data-count`. @@ -2176,8 +2494,8 @@ you can issue the following command: .. _dataverse.pid.datacite.username: -dataverse.pid.datacite.username -+++++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.datacite.username ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DataCite uses `HTTP Basic authentication `_ for `Fabrica `_ and their APIs. You need to provide @@ -2198,8 +2516,8 @@ Once you have a username from DataCite, you can enter it like this: .. _dataverse.pid.datacite.password: -dataverse.pid.datacite.password -+++++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.datacite.password ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Once you have a password from your provider, you should create a password alias. This avoids storing it in clear text, although you could use a JVM option `to reference @@ -2225,8 +2543,8 @@ To manage these, read up on `Payara docs about password aliases `. @@ -2247,8 +2565,8 @@ and re-add it. .. _dataverse.pid.handlenet.key.passphrase: -dataverse.pid.handlenet.key.passphrase -++++++++++++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.handlenet.key.passphrase +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Related to :ref:`Handle.Net PID provider usage `. @@ -2268,8 +2586,8 @@ the old JVM option and the wrapped password alias, then recreate as shown for .. _dataverse.pid.handlenet.index: -dataverse.pid.handlenet.index -+++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.handlenet.index ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Related to :ref:`Handle.Net PID provider usage `. @@ -2287,8 +2605,8 @@ re-add it. .. _dataverse.pid.permalink.base-url: -dataverse.pid.permalink.base-url -++++++++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.permalink.base-url +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ When using :ref:`PermaLinks `, this setting can be used to configure an external resolver. Dataverse will associate a PermaLink PID with the URL: ``/citation?persistentId=perma:``. The default value is your Dataverse site URL, which will result in PermaLinks correctly resolving to the appropriate dataset page. @@ -2309,8 +2627,8 @@ variable ``DATAVERSE_PID_PERMALINK_BASE_URL``. This setting was formerly known a .. _dataverse.pid.ezid.api-url: -dataverse.pid.ezid.api-url -++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.ezid.api-url +++++++++++++++++++++++++++++++++++++++++++++++++++++++ The EZID DOI provider is likely not an option if you are `not associated with California Digital Library (CDL) or Purdue University @@ -2324,8 +2642,8 @@ variable ``DATAVERSE_PID_EZID_API_URL``. This setting was formerly known as .. _dataverse.pid.ezid.username: -dataverse.pid.ezid.username -+++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.ezid.username ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The EZID DOI provider is likely not an option if you are `not associated with California Digital Library (CDL) or Purdue University @@ -2342,8 +2660,8 @@ should delete and re-add it. .. _dataverse.pid.ezid.password: -dataverse.pid.ezid.password -+++++++++++++++++++++++++++ +Legacy Single PID Provider: dataverse.pid.ezid.password ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The EZID DOI provider is likely not an option if you are `not associated with California Digital Library (CDL) or Purdue University @@ -2805,8 +3123,8 @@ By default the footer says "Copyright © [YYYY]" but you can add text after the .. _:DoiProvider: -:DoiProvider -++++++++++++ +Legacy Single PID Provider: :DoiProvider +++++++++++++++++++++++++++++++++++++++++ As of this writing "DataCite" and "EZID" are the only valid options for production installations. Developers using Dataverse Software 4.10+ are welcome to use the keyword "FAKE" to configure a non-production installation with an @@ -2826,8 +3144,8 @@ JVM options: .. _:Protocol: -:Protocol -+++++++++ +Legacy Single PID Provider: :Protocol ++++++++++++++++++++++++++++++++++++++ As of this writing "doi","hdl", and "perma" are the only valid option for the protocol for a persistent ID. @@ -2835,8 +3153,8 @@ As of this writing "doi","hdl", and "perma" are the only valid option for the pr .. _:Authority: -:Authority -++++++++++ +Legacy Single PID Provider: :Authority +++++++++++++++++++++++++++++++++++++++ Use the authority assigned to you by your DoiProvider or HandleProvider, or your choice if using PermaLinks. @@ -2846,8 +3164,8 @@ Please note that a DOI or Handle authority cannot have a slash ("/") in it (slas .. _:Shoulder: -:Shoulder -+++++++++ +Legacy Single PID Provider: :Shoulder ++++++++++++++++++++++++++++++++++++++ The shoulder is used with DOIs and PermaLinks. Out of the box, the shoulder is set to "FK2/" but this is for testing only! When you apply for your DOI authority/namespace, you may have been assigned a shoulder. The following is only an example and a trailing slash is optional. @@ -2855,8 +3173,8 @@ The shoulder is used with DOIs and PermaLinks. Out of the box, the shoulder is s .. _:IdentifierGenerationStyle: -:IdentifierGenerationStyle -++++++++++++++++++++++++++ +Legacy Single PID Provider: :IdentifierGenerationStyle +++++++++++++++++++++++++++++++++++++++++++++++++++++++ By default, the Dataverse Software generates a random 6 character string, pre-pended by the Shoulder if set, to use as the identifier for a Dataset. @@ -2894,8 +3212,8 @@ more details. .. _:DataFilePIDFormat: -:DataFilePIDFormat -++++++++++++++++++ +Legacy Single PID Provider: :DataFilePIDFormat +++++++++++++++++++++++++++++++++++++++++++++++ This setting controls the way that the "identifier" component of a file's persistent identifier (PID) relates to the PID of its "parent" dataset. @@ -2985,8 +3303,8 @@ When :AllowEnablingFilePIDsPerCollection is true, setting File PIDs to be enable .. _:IndependentHandleService: -:IndependentHandleService -+++++++++++++++++++++++++ +Legacy Single PID Provider: :IndependentHandleService ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Specific for Handle PIDs. Set this setting to true if you want to use a Handle service which is setup to work 'independently' (No communication with the Global Handle Registry). By default this setting is absent and the Dataverse Software assumes it to be false. @@ -2995,8 +3313,8 @@ By default this setting is absent and the Dataverse Software assumes it to be fa .. _:HandleAuthHandle: -:HandleAuthHandle -+++++++++++++++++ +Legacy Single PID Provider: :HandleAuthHandle ++++++++++++++++++++++++++++++++++++++++++++++ Specific for Handle PIDs. Set this setting to / to be used on a global handle service when the public key is NOT stored in the default handle. By default this setting is absent and the Dataverse Software assumes it to be not set. If the public key for instance is stored in handle: 21.T12996/USER01. From d13a70e7cc550f00e7323fb8a12e552c0c90768d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 18 Jan 2024 18:01:50 -0500 Subject: [PATCH 062/113] add test urls as default --- .../iq/dataverse/pidproviders/DataCiteProviderFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java index a78b7aa8e4c..f43c0f41bea 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java @@ -25,8 +25,8 @@ public PidProvider createPidProvider(String providerId) { String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - String mdsUrl = JvmSettings.DATACITE_MDS_API_URL.lookup(providerId); - String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookup(providerId); + String mdsUrl = JvmSettings.DATACITE_MDS_API_URL.lookupOptional(providerId).orElse("https://mds.test.datacite.org"); + String apiUrl = JvmSettings.DATACITE_REST_API_URL.lookupOptional(providerId).orElse("https://api.test.datacite.org"); String username = JvmSettings.DATACITE_USERNAME.lookup(providerId); String password = JvmSettings.DATACITE_PASSWORD.lookup(providerId); From 30d69299746d8a054319ce6b5330829c834523f7 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 18 Jan 2024 18:02:16 -0500 Subject: [PATCH 063/113] cleanup -remove unused imports --- .../harvard/iq/dataverse/pidproviders/PidProvider.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index 2b2fe2ee07b..ddd26bd4c35 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -1,17 +1,8 @@ package edu.harvard.iq.dataverse.pidproviders; -import edu.harvard.iq.dataverse.DataFile; -import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.engine.command.CommandContext; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; - -import static edu.harvard.iq.dataverse.pidproviders.PidProvider.logger; - import java.util.*; -import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; public interface PidProvider { From 17809f1f556c8a912ca9618066364e19b08976a6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 19 Jan 2024 09:43:35 -0500 Subject: [PATCH 064/113] unrelated link fix --- doc/sphinx-guides/source/developers/deployment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/developers/deployment.rst b/doc/sphinx-guides/source/developers/deployment.rst index 045b0d0abbc..f4566b9da5f 100755 --- a/doc/sphinx-guides/source/developers/deployment.rst +++ b/doc/sphinx-guides/source/developers/deployment.rst @@ -114,7 +114,7 @@ Please note that while the script should work well on new-ish branches, older br Migrating Datafiles from Local Storage to S3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A number of pilot Dataverse installations start on local storage, then administrators are tasked with migrating datafiles into S3 or similar object stores. The files may be copied with a command-line utility such as `s3cmd`. You will want to retain the local file hierarchy, keeping the authority (for example: 10.5072) at the bucket "root." +A number of pilot Dataverse installations start on local storage, then administrators are tasked with migrating datafiles into S3 or similar object stores. The files may be copied with a command-line utility such as `s3cmd `_. You will want to retain the local file hierarchy, keeping the authority (for example: 10.5072) at the bucket "root." The below example queries may assist with updating dataset and datafile locations in the Dataverse installation's PostgresQL database. Depending on the initial version of the Dataverse Software and subsequent upgrade path, Datafile storage identifiers may or may not include a ``file://`` prefix, so you'll want to catch both cases. From af0349334717de7f4ee617e7969abb468894fd4d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 24 Jan 2024 12:05:09 -0500 Subject: [PATCH 065/113] fix for #10251 - sync terms popup required code --- .../harvard/iq/dataverse/util/FileUtil.java | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 776d04e98cc..8decf74fe13 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -1199,34 +1199,12 @@ public static boolean isGuestbookPopupRequired(DatasetVersion datasetVersion) { } public static boolean isTermsPopupRequired(DatasetVersion datasetVersion) { - - if (datasetVersion == null) { - logger.fine("TermsPopup not required because datasetVersion is null."); - return false; - } - //0. if version is draft then Popup "not required" - if (!datasetVersion.isReleased()) { - logger.fine("TermsPopup not required because datasetVersion has not been released."); + Boolean answer = popupDueToStateOrTerms(datasetVersion); + if(answer == null) { + logger.fine("TermsPopup is not required."); return false; } - // 1. License and Terms of Use: - if (datasetVersion.getTermsOfUseAndAccess() != null) { - if (!License.CC0.equals(datasetVersion.getTermsOfUseAndAccess().getLicense()) - && !(datasetVersion.getTermsOfUseAndAccess().getTermsOfUse() == null - || datasetVersion.getTermsOfUseAndAccess().getTermsOfUse().equals(""))) { - logger.fine("TermsPopup required because of license or terms of use."); - return true; - } - - // 2. Terms of Access: - if (!(datasetVersion.getTermsOfUseAndAccess().getTermsOfAccess() == null) && !datasetVersion.getTermsOfUseAndAccess().getTermsOfAccess().equals("")) { - logger.fine("TermsPopup required because of terms of access."); - return true; - } - } - - logger.fine("TermsPopup is not required."); - return false; + return answer; } /** From be542c5ac7096ae5e635ebfcb73fac0fa1bffd51 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 25 Jan 2024 18:17:45 -0500 Subject: [PATCH 066/113] API calls for getting provider info and changing PID Generators --- .../harvard/iq/dataverse/api/Datasets.java | 83 +++++++++++++++++++ .../edu/harvard/iq/dataverse/api/Pids.java | 37 +++++++++ .../pidproviders/AbstractPidProvider.java | 22 +++++ .../dataverse/pidproviders/PidProvider.java | 9 ++ .../iq/dataverse/pidproviders/PidUtil.java | 8 ++ 5 files changed, 159 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 3a2497d9418..92e2d3715dc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -39,6 +39,7 @@ import edu.harvard.iq.dataverse.makedatacount.*; import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean.MakeDataCountEntry; import edu.harvard.iq.dataverse.metrics.MetricsUtil; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -4603,4 +4604,86 @@ public Response getCanDownloadAtLeastOneFile(@Context ContainerRequestContext cr return ok(permissionService.canDownloadAtLeastOneFile(req, datasetVersion)); }, getRequestUser(crc)); } + + @GET + @AuthRequired + @Path("{identifier}/pidGenerator") + public Response getPidGenerator(@Context ContainerRequestContext crc, @PathParam("identifier") String dvIdtf, + @Context HttpHeaders headers) throws WrappedResponse { + + Dataset dataset; + + try { + dataset = findDatasetOrDie(dvIdtf); + } catch (WrappedResponse ex) { + return error(Response.Status.NOT_FOUND, "No such dataset"); + } + String pidGeneratorId = dataset.getPidGeneratorId(); + return ok(pidGeneratorId); + } + + @PUT + @AuthRequired + @Path("{identifier}/pidGenerator") + public Response setPidGenerator(@Context ContainerRequestContext crc, @PathParam("identifier") String datasetId, + String generatorId, @Context HttpHeaders headers) throws WrappedResponse { + + // Superuser-only: + AuthenticatedUser user; + try { + user = getRequestAuthenticatedUserOrDie(crc); + } catch (WrappedResponse ex) { + return error(Response.Status.UNAUTHORIZED, "Authentication is required."); + } + if (!user.isSuperuser()) { + return error(Response.Status.FORBIDDEN, "Superusers only."); + } + + Dataset dataset; + + try { + dataset = findDatasetOrDie(datasetId); + } catch (WrappedResponse ex) { + return error(Response.Status.NOT_FOUND, "No such dataset"); + } + if (PidUtil.getManagedProviderIds().contains(generatorId)) { + dataset.setPidGeneratorId(generatorId); + datasetService.merge(dataset); + return ok("PID Generator set to: " + generatorId); + } else { + return error(Response.Status.NOT_FOUND, "No PID Generator found for the give id"); + } + + } + + @DELETE + @AuthRequired + @Path("{identifier}/pidGenerator") + public Response resetPidGenerator(@Context ContainerRequestContext crc, @PathParam("identifier") String dvIdtf, + @Context HttpHeaders headers) throws WrappedResponse { + + // Superuser-only: + AuthenticatedUser user; + try { + user = getRequestAuthenticatedUserOrDie(crc); + } catch (WrappedResponse ex) { + return error(Response.Status.BAD_REQUEST, "Authentication is required."); + } + if (!user.isSuperuser()) { + return error(Response.Status.FORBIDDEN, "Superusers only."); + } + + Dataset dataset; + + try { + dataset = findDatasetOrDie(dvIdtf); + } catch (WrappedResponse ex) { + return error(Response.Status.NOT_FOUND, "No such dataset"); + } + + dataset.setPidGenerator(null); + datasetService.merge(dataset); + return ok("Pid Generator reset to default: " + dataset.getEffectivePidGenerator().getId()); + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Pids.java b/src/main/java/edu/harvard/iq/dataverse/api/Pids.java index 534e42fd505..4ad57bceb58 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Pids.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Pids.java @@ -130,4 +130,41 @@ public Response deletePid(@Context ContainerRequestContext crc, @PathParam("id") } } + @GET + @AuthRequired + @Path("providers") + @Produces(MediaType.APPLICATION_JSON) + public Response getPidProviders(@Context ContainerRequestContext crc) throws WrappedResponse { + try { + getRequestAuthenticatedUserOrDie(crc); + } catch (WrappedResponse ex) { + return ex.getResponse(); + } + return ok(PidUtil.getProviders()); + } + + @GET + @AuthRequired + // The :.+ suffix allows PIDs with a / char to be entered w/o escaping + @Path("providers/{persistentId:.+}") + @Produces(MediaType.APPLICATION_JSON) + public Response getPidProviderId(@Context ContainerRequestContext crc, @PathParam("persistentId") String persistentId) throws WrappedResponse { + try { + getRequestAuthenticatedUserOrDie(crc); + } catch (WrappedResponse ex) { + return ex.getResponse(); + } + GlobalId globalId = PidUtil.parseAsGlobalID(persistentId); + if(globalId== null) { + return error(Response.Status.NOT_FOUND, "No provider found for PID"); + } else { + String providerId = globalId.getProviderId(); + if(PidUtil.getManagedProviderIds().contains(providerId)) { + return ok(globalId.getProviderId()); + } else { + return ok("PID recognized as an unmanaged " + globalId.getProtocol()); + } + } + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 40063907c78..f75132e6697 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -7,6 +7,10 @@ import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.util.SystemConfig; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; + import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.*; @@ -19,6 +23,8 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import com.beust.jcommander.Strings; + public abstract class AbstractPidProvider implements PidProvider { private static final Logger logger = Logger.getLogger(AbstractPidProvider.class.getCanonicalName()); @@ -849,4 +855,20 @@ public boolean canCreatePidsLike(GlobalId pid) { return canManagePID() && !managedSet.contains(pid.asString()) && (getIdentifierGenerationStyle().equals("INDEPENDENT") || getId().equals(pid.getProviderId())); } + + @Override + public JsonObject getProviderSpecification() { + JsonObjectBuilder providerSpecification = Json.createObjectBuilder(); + providerSpecification.add("id", id); + providerSpecification.add("label", label); + providerSpecification.add("protocol", protocol); + providerSpecification.add("authority", authority); + providerSpecification.add("separator", getSeparator()); + providerSpecification.add("shoulder", shoulder); + providerSpecification.add("identifierGenerationStyle", identifierGenerationStyle); + providerSpecification.add("datafilePidFormat", datafilePidFormat); + providerSpecification.add("managedSet", Strings.join(",", managedSet.toArray())); + providerSpecification.add("excludedSet", Strings.join(",", excludedSet.toArray())); + return providerSpecification.build(); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java index ddd26bd4c35..ea3a243f25c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java @@ -2,6 +2,9 @@ import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; + import java.util.*; import java.util.logging.Logger; @@ -177,4 +180,10 @@ static boolean checkDOIAuthority(String doiAuthority){ */ boolean canCreatePidsLike(GlobalId pid); + /** + * Returns a JSON representation of this pid provider including it's id, label, protocol, authority, separator, and identifier. + * @return + */ + public JsonObject getProviderSpecification(); + } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index 54f39fc1e1a..bbf56cdfe83 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -271,4 +271,12 @@ public static PidProvider getPidProvider(String protocol, String authority, Stri public static Set getManagedProviderIds() { return providerMap.keySet(); } + + public static JsonObject getProviders() { + JsonObjectBuilder builder = Json.createObjectBuilder(); + for (PidProvider pidProvider : providerMap.values()) { + builder.add(pidProvider.getId(), pidProvider.getProviderSpecification()); + } + return builder.build(); + } } From 14af132895ca7b4eca3777660c954c1ea29883d2 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 25 Jan 2024 18:18:01 -0500 Subject: [PATCH 067/113] api docs --- doc/sphinx-guides/source/api/native-api.rst | 100 ++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index dbe769e2fd1..a0468677af2 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2709,6 +2709,56 @@ The fully expanded example above (without environment variables) looks like this curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/datasets/24/versions/1.0/canDownloadAtLeastOneFile" +.. _dataset-pid-generator: + +Configure The PID Generator a Dataset Uses (If Enabled) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Dataverse can be configured to use multiple PID Providers (see the :ref:`_pids-configuration` section for more information). +When there are multiple PID Providers and File PIDs are enabled, it is possible to set which provider will be used to generate (mint) those PIDs. +While it usually makes sense to use the same PID Provider that manages the dataset PID, there are cases, specifically if the PID Provider for the dataset PID cannot generate +other PIDs with the same authority/shoulder, etc. as in the dataset PID, where another Provider is needed. Dataverse has a set of API calls to see what PID provider will be +used to generate datafile PIDs and, as a superuser, to change it (to a new one or back to a default). + +To see the current choice for this dataset: + +.. code-block:: bash + + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_IDENTIFIER=doi:10.5072/FK2/YD5QDG + + curl "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" + + The response will be the id of the PID Provider that will be used. Details of that provider's configration can be obtained via the :ref:`_pids-providers-api`. + +To set the behavior for this dataset: + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_IDENTIFIER=doi:10.5072/FK2/YD5QDG + export GENERATOR_ID=perma1 + + curl -X PUT -H "X-Dataverse-key:$API_TOKEN" -H Content-type:application/json -d $GENERATOR_ID "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" + + + The PID Provider id used must be one of the those configured - see :ref:`_pids-providers-api`. + The return status code may be 200/OK, 401/403 if an api key is not sent or the user is not a superuser, or 404 if the dataset or PID provider are not found. + Note that using a PIDProvider that generates DEPENDENT datafile PIDs that doesn't share the dataset PID's protocol/authority/separator/shoulder is not supported. (INDEPENDENT should be used in this case see the :ref:`_pids-configuration` section for more information). + +The API can also be used to reset the dataset to use the default/inherited value: + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_IDENTIFIER=doi:10.5072/FK2/YD5QDG + + curl -X DELETE -H "X-Dataverse-key:$API_TOKEN" -H Content-type:application/json "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" + + The default will always be the same provider as for the dataset PID if that provider can generate new PIDs, and will be the PID Provider set for the collection or the global default otherwise. + Files ----- @@ -4590,6 +4640,56 @@ The fully expanded example above (without environment variables) looks like this curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE "https://demo.dataverse.org/api/pids/:persistentId/delete?persistentId=doi:10.70122/FK2/9BXT5O" +.. _pids-providers-api: + +Get Information about Configured PID Providers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Dataverse can be configured with one or more PID Providers that it uses to create new PIDs and manage existing ones. +This API call returns a JSONObject listing the configured providers and details about the protocol/authority/separator/shoulder they manage, +along with information about about how new dataset and datafile PIDs are generated. See the :ref:`_pids-configuration` section for more information. + +.. note:: See :ref:`curl-examples-and-environment-variables` if you are unfamiliar with the use of export below. + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + + curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/pids/providers" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/pids/providers" + +Get the id of the PID Provider Managing a Given PID +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Dataverse can be configured with one or more PID Providers that it uses to create new PIDs and manage existing ones. +This API call returns the string id of the PID Provider than manages a given PID. See the :ref:`_pids-configuration` section for more information. +Delete PID (this is only possible for PIDs that are in the "draft" state) and within a Dataverse installation, set ``globalidcreatetime`` to null and ``identifierregistered`` to false. A superuser API token is required. + +.. note:: See :ref:`curl-examples-and-environment-variables` if you are unfamiliar with the use of export below. + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PID=doi:10.70122/FK2/9BXT5O + + curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/pids/providers/$PID" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/pids/providers/doi:10.70122/FK2/9BXT5O" + +If the PID is not managed by Dataverse, this call will report if the PID is recognized as a valid PID for a given protocol (doi, hdl, or perma) + or will return a 400/Bad Request response if it is not. + .. _admin: From d3a1aeae8d88c6c9ce82abada310d17656c0a48f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 26 Jan 2024 12:42:09 -0500 Subject: [PATCH 068/113] change level for entries to fix build error --- .../source/installation/config.rst | 112 +++++++++--------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 9a6a9def1d1..c492e502e15 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -247,14 +247,14 @@ to be compatible with the MicroProfile specification which means that letters. Example: ``dataverse.pid.default-provider`` -> ``DATAVERSE_PID_DEFAULT_PROVIDER`` Global Settings -############### +^^^^^^^^^^^^^^^ The following three global settings are required to configure PID Providers in the Dataverse software: .. _dataverse.pid.providers: dataverse.pid.providers -####################### +^^^^^^^^^^^^^^^^^^^^^^^ A comma-separated list of the ids of the PID providers to use. IDs should be simple unique text strings, e.g. datacite1, perma1, etc. IDs are used to scope the provider-specific settings but are not directly visible to users. @@ -262,48 +262,48 @@ IDs are used to scope the provider-specific settings but are not directly visibl .. _dataverse.pid.default-provider: dataverse.pid.default-provider -############################## +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ID of the default PID provider to use. .. _dataverse.pid.provider-implementations-directory: dataverse.pid.provider-implementations-directory -################################################ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The path to the directory where JAR files containing additional types of PID Providers can be added. Dataverse includes providers that support DOIs (DataCite, EZId, or FAKE), Handles, and PermaLinks. PID provider jar files added to this directory can replace any of these or add new PID Providers. Per-Provider Settings -##################### +^^^^^^^^^^^^^^^^^^^^^ Each Provider listed by id in the dataverse.pid.providers setting must be configured with the following common settings and any settings that are specific to the provider type. .. _dataverse.pid.*.type: -dataverse.pid.\*.type -#################### +dataverse.pid.*.type +^^^^^^^^^^^^^^^^^^^^ The Provider type, currently one of ``datacite``, ``ezid``, ``FAKE``, ``hdl``, or ``perma``. The type defines which protocol a service supports (DOI, Handle, or PermaLink) and, for DOI Providers, which DOI service is used. .. _dataverse.pid.*.label: -dataverse.pid.\*.label -###################### +dataverse.pid.*.label +^^^^^^^^^^^^^^^^^^^^^ A human-readable label for the provider .. _dataverse.pid.*.authority: -dataverse.pid.\*.authority -########################## +dataverse.pid.*.authority +^^^^^^^^^^^^^^^^^^^^^^^^^ .. _dataverse.pid.*.shoulder: -dataverse.pid.\*.shoulder -######################### +dataverse.pid.*.shoulder +^^^^^^^^^^^^^^^^^^^^^^^^ In general, PIDs are of the form ``:/*`` where ``*`` is the portion unique to an individual PID. PID Providers must define the authority and shoulder (with the protocol defined by the ``dataverse.pid.*.type`` setting) that defines the set of existing PIDs they can manage and the prefix they can use when minting new PIDs. @@ -311,8 +311,8 @@ the authority and shoulder (with the protocol defined by the ``dataverse.pid.*.t .. _dataverse.pid.*.identifier-generation-style: -dataverse.pid.\*.identifier-generation-style -############################################ +dataverse.pid.*.identifier-generation-style +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default, Pid Providers in Dataverse generate a random 6 character string, pre-pended by the Shoulder if set, to use as the identifier for a Dataset. @@ -350,8 +350,8 @@ setting below to determine how datafile identifiers are generated. .. _dataverse.pid.*.datafile-pid-format: -dataverse.pid.\*.datafile-pid-format -#################################### +dataverse.pid.*.datafile-pid-format +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This setting controls the way that the "identifier" component of a file's persistent identifier (PID) relates to the PID of its "parent" dataset - for a give PID Provider. @@ -407,13 +407,13 @@ timestamps. .. _dataverse.pid.*.managed-list: -dataverse.pid.\*.managed-list -############################# +dataverse.pid.*.managed-list +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _dataverse.pid.*.excluded-list: -dataverse.pid.\*.excluded-list -############################## +dataverse.pid.*.excluded-list +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ With at least some PID services, it is possible for the authority(permission) to manage specific individual PIDs to be transferred between accounts. To handle these cases, the individual PIDs, written in the @@ -428,16 +428,16 @@ with the default assumption that these lists are empty. .. _dataverse.pid.*.datacite: DataCite-specific Settings -########################## +^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.datacite.mds-api-url -##################################### -dataverse.pid.\*.datacite.rest-api-url -###################################### -dataverse.pid.\*.datacite.username -################################## -dataverse.pid.\*.datacite.password -################################## +dataverse.pid.*.datacite.mds-api-url +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +dataverse.pid.*.datacite.rest-api-url +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +dataverse.pid.*.datacite.username +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +dataverse.pid.*.datacite.password +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PID Providers of type ``datacite`` require four additional parameters that define how the provider connects to DataCite. DataCite has two APIs that are used in Dataverse: @@ -457,14 +457,14 @@ As noted above, you should use one of the more secure options for setting the pa .. _dataverse.pid.*.ezid: EZId-specific Settings -###################### +^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.ezid.api-url -############################# -dataverse.pid.\*.ezid.username -############################## -dataverse.pid.\*.ezid.password -############################## +dataverse.pid.*.ezid.api-url +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +dataverse.pid.*.ezid.username +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +dataverse.pid.*.ezid.password +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Note that use of `EZId `_ is limited primarily to University of California institutions. If you have an EZId account, you will need to configure the ``api-url`` and your account ``username`` and ``password``. As above, you should use one of the more secure @@ -473,13 +473,13 @@ options for setting the password. .. _dataverse.pid.*.permalink: PermaLink-specific Settings -########################### +^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.permalink.base-url -################################### +dataverse.pid.*.permalink.base-url +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.permalink.separator -#################################### +dataverse.pid.*.permalink.separator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PermaLinks are a simple PID option intended for intranet and catalog use cases. They can be used without an external service or be configured with the ``base-url`` of a resolution service. PermaLinks also allow a custom ``separator`` to be used. (Note: when using multiple @@ -488,25 +488,25 @@ PermaLink providers, you should avoid ambiguous authority/separator/shoulder com .. _dataverse.pid.*.handlenet: Handle-specific Settings -######################## +^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.handlenet.index -################################ +dataverse.pid.*.handlenet.index +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.handlenet.independent-service -############################################## +dataverse.pid.*.handlenet.independent-service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.handlenet.auth-handle -###################################### +dataverse.pid.*.handlenet.auth-handle +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.handlenet.key -############################## +dataverse.pid.*.handlenet.key +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.handlenet.path -############################### +dataverse.pid.*.handlenet.path +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -dataverse.pid.\*.handlenet.passphrase -##################################### +dataverse.pid.*.handlenet.passphrase +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Note: If you are **minting your own handles** and plan to set up your own handle service, please refer to `Handle.Net documentation `_. @@ -546,7 +546,7 @@ While using the PID Provider configuration settings described above is recommend only using a single PID Provider can use the settings below instead. In general, these legacy settings mirror those above except for not including a PID Provider id. -Configuring Your Dataverse Installation for a SIngle DOI Provider +Configuring Your Dataverse Installation for a Single DOI Provider ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here are the configuration options for DOIs.: From ec63260f84642a3049e8a42000511fa5f0eeaa1f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 26 Jan 2024 13:03:10 -0500 Subject: [PATCH 069/113] typo in refs --- doc/sphinx-guides/source/api/native-api.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index a0468677af2..dc22dd1eeee 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2714,7 +2714,7 @@ The fully expanded example above (without environment variables) looks like this Configure The PID Generator a Dataset Uses (If Enabled) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Dataverse can be configured to use multiple PID Providers (see the :ref:`_pids-configuration` section for more information). +Dataverse can be configured to use multiple PID Providers (see the :ref:`pids-configuration` section for more information). When there are multiple PID Providers and File PIDs are enabled, it is possible to set which provider will be used to generate (mint) those PIDs. While it usually makes sense to use the same PID Provider that manages the dataset PID, there are cases, specifically if the PID Provider for the dataset PID cannot generate other PIDs with the same authority/shoulder, etc. as in the dataset PID, where another Provider is needed. Dataverse has a set of API calls to see what PID provider will be @@ -2745,7 +2745,7 @@ To set the behavior for this dataset: The PID Provider id used must be one of the those configured - see :ref:`_pids-providers-api`. The return status code may be 200/OK, 401/403 if an api key is not sent or the user is not a superuser, or 404 if the dataset or PID provider are not found. - Note that using a PIDProvider that generates DEPENDENT datafile PIDs that doesn't share the dataset PID's protocol/authority/separator/shoulder is not supported. (INDEPENDENT should be used in this case see the :ref:`_pids-configuration` section for more information). + Note that using a PIDProvider that generates DEPENDENT datafile PIDs that doesn't share the dataset PID's protocol/authority/separator/shoulder is not supported. (INDEPENDENT should be used in this case see the :ref:`pids-configuration` section for more information). The API can also be used to reset the dataset to use the default/inherited value: @@ -4647,7 +4647,7 @@ Get Information about Configured PID Providers Dataverse can be configured with one or more PID Providers that it uses to create new PIDs and manage existing ones. This API call returns a JSONObject listing the configured providers and details about the protocol/authority/separator/shoulder they manage, -along with information about about how new dataset and datafile PIDs are generated. See the :ref:`_pids-configuration` section for more information. +along with information about about how new dataset and datafile PIDs are generated. See the :ref:`pids-configuration` section for more information. .. note:: See :ref:`curl-examples-and-environment-variables` if you are unfamiliar with the use of export below. @@ -4668,7 +4668,7 @@ Get the id of the PID Provider Managing a Given PID ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Dataverse can be configured with one or more PID Providers that it uses to create new PIDs and manage existing ones. -This API call returns the string id of the PID Provider than manages a given PID. See the :ref:`_pids-configuration` section for more information. +This API call returns the string id of the PID Provider than manages a given PID. See the :ref:`pids-configuration` section for more information. Delete PID (this is only possible for PIDs that are in the "draft" state) and within a Dataverse installation, set ``globalidcreatetime`` to null and ``identifierregistered`` to false. A superuser API token is required. .. note:: See :ref:`curl-examples-and-environment-variables` if you are unfamiliar with the use of export below. From 52fdabaf2c64d58e986e00d194e48b9891ddefc0 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 26 Jan 2024 13:11:59 -0500 Subject: [PATCH 070/113] fix indents --- doc/sphinx-guides/source/api/native-api.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index dc22dd1eeee..373a12f326b 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2729,7 +2729,7 @@ To see the current choice for this dataset: curl "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" - The response will be the id of the PID Provider that will be used. Details of that provider's configration can be obtained via the :ref:`_pids-providers-api`. +The response will be the id of the PID Provider that will be used. Details of that provider's configration can be obtained via the :ref:`_pids-providers-api`. To set the behavior for this dataset: @@ -2743,9 +2743,9 @@ To set the behavior for this dataset: curl -X PUT -H "X-Dataverse-key:$API_TOKEN" -H Content-type:application/json -d $GENERATOR_ID "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" - The PID Provider id used must be one of the those configured - see :ref:`_pids-providers-api`. - The return status code may be 200/OK, 401/403 if an api key is not sent or the user is not a superuser, or 404 if the dataset or PID provider are not found. - Note that using a PIDProvider that generates DEPENDENT datafile PIDs that doesn't share the dataset PID's protocol/authority/separator/shoulder is not supported. (INDEPENDENT should be used in this case see the :ref:`pids-configuration` section for more information). +The PID Provider id used must be one of the those configured - see :ref:`_pids-providers-api`. +The return status code may be 200/OK, 401/403 if an api key is not sent or the user is not a superuser, or 404 if the dataset or PID provider are not found. +Note that using a PIDProvider that generates DEPENDENT datafile PIDs that doesn't share the dataset PID's protocol/authority/separator/shoulder is not supported. (INDEPENDENT should be used in this case see the :ref:`pids-configuration` section for more information). The API can also be used to reset the dataset to use the default/inherited value: @@ -2757,7 +2757,7 @@ The API can also be used to reset the dataset to use the default/inherited value curl -X DELETE -H "X-Dataverse-key:$API_TOKEN" -H Content-type:application/json "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" - The default will always be the same provider as for the dataset PID if that provider can generate new PIDs, and will be the PID Provider set for the collection or the global default otherwise. +The default will always be the same provider as for the dataset PID if that provider can generate new PIDs, and will be the PID Provider set for the collection or the global default otherwise. Files ----- From 19c511e5167dc9726ec6a1d04e94ed454d28cf96 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 26 Jan 2024 13:17:19 -0500 Subject: [PATCH 071/113] more bad refs --- doc/sphinx-guides/source/api/native-api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 373a12f326b..9bc95848c28 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2729,7 +2729,7 @@ To see the current choice for this dataset: curl "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" -The response will be the id of the PID Provider that will be used. Details of that provider's configration can be obtained via the :ref:`_pids-providers-api`. +The response will be the id of the PID Provider that will be used. Details of that provider's configration can be obtained via the :ref:`pids-providers-api`. To set the behavior for this dataset: @@ -2743,7 +2743,7 @@ To set the behavior for this dataset: curl -X PUT -H "X-Dataverse-key:$API_TOKEN" -H Content-type:application/json -d $GENERATOR_ID "$SERVER_URL/api/datasets/:persistentId/pidGenerator?persistentId=$PERSISTENT_IDENTIFIER" -The PID Provider id used must be one of the those configured - see :ref:`_pids-providers-api`. +The PID Provider id used must be one of the those configured - see :ref:`pids-providers-api`. The return status code may be 200/OK, 401/403 if an api key is not sent or the user is not a superuser, or 404 if the dataset or PID provider are not found. Note that using a PIDProvider that generates DEPENDENT datafile PIDs that doesn't share the dataset PID's protocol/authority/separator/shoulder is not supported. (INDEPENDENT should be used in this case see the :ref:`pids-configuration` section for more information). From bb7b943fce6ffcb8cf887966c3da089484053faf Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 26 Jan 2024 14:00:52 -0500 Subject: [PATCH 072/113] support for legacy hdl, perma, ezid --- .../pidproviders/PidProviderFactoryBean.java | 69 ++++++++++++------- .../iq/dataverse/settings/JvmSettings.java | 17 +++++ .../settings/SettingsServiceBean.java | 6 +- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 2b3190f738f..ee7093aa6bb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -138,34 +138,53 @@ private void loadProviders() { .getValueForKey(SettingsServiceBean.Key.IdentifierGenerationStyle, "random"); String dataFilePidFormat = settingsService.getValueForKey(SettingsServiceBean.Key.DataFilePIDFormat, "DEPENDENT"); - switch (provider) { - case "EZID": - /* - * String baseUrl = JvmSettings.PID_EZID_BASE_URL.lookup(String.class); String - * username = JvmSettings.PID_EZID_USERNAME.lookup(String.class); String - * password = JvmSettings.PID_EZID_PASSWORD.lookup(String.class); - * PidUtil.addToProviderList( new EZIdDOIProvider("legacy", "legacy", authority, - * shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", baseUrl, - * username, password)); - */ - break; - case "DataCite": - String mdsUrl = JvmSettings.LEGACY_DATACITE_MDS_API_URL.lookup(String.class); - String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(String.class); - //Defaults for testing where no account is set up - String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(String.class); - String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(String.class); - if (mdsUrl != null && restUrl != null && dcUsername != null && dcPassword != null) { - legacy = new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, - identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, - dcPassword); + switch (protocol) { + case "doi": + switch (provider) { + case "EZID": + + String baseUrl = JvmSettings.LEGACY_EZID_API_URL.lookup(); + String username = JvmSettings.LEGACY_EZID_USERNAME.lookup(); + String password = JvmSettings.LEGACY_EZID_PASSWORD.lookup(); + PidUtil.addToProviderList(new EZIdDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", "", baseUrl, username, password)); + + break; + case "DataCite": + String mdsUrl = JvmSettings.LEGACY_DATACITE_MDS_API_URL.lookup(); + String restUrl = JvmSettings.LEGACY_DATACITE_REST_API_URL.lookup(); + // Defaults for testing where no account is set up + String dcUsername = JvmSettings.LEGACY_DATACITE_USERNAME.lookup(); + String dcPassword = JvmSettings.LEGACY_DATACITE_PASSWORD.lookup(); + if (mdsUrl != null && restUrl != null && dcUsername != null && dcPassword != null) { + legacy = new DataCiteDOIProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", "", mdsUrl, restUrl, dcUsername, + dcPassword); + } + break; + case "FAKE": + logger.warning("Adding FAKE provider"); + legacy = new FakeDOIProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, + dataFilePidFormat, "", ""); + break; } break; - case "FAKE": - logger.warning("Adding FAKE provider"); - legacy = new FakeDOIProvider("legacy", "legacy", authority, shoulder, - identifierGenerationStyle, dataFilePidFormat, "", ""); + case "hdl": + int index = JvmSettings.LEGACY_HANDLENET_INDEX.lookup(Integer.class); + String path = JvmSettings.LEGACY_HANDLENET_KEY_PATH.lookup(); + String passphrase = JvmSettings.LEGACY_HANDLENET_KEY_PASSPHRASE.lookup(); + boolean independentHandleService = settingsService + .isTrueForKey(SettingsServiceBean.Key.IndependentHandleService, false); + String handleAuthHandle = settingsService.getValueForKey(SettingsServiceBean.Key.HandleAuthHandle); + + legacy = new HandlePidProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, + dataFilePidFormat, "", "", index, independentHandleService, handleAuthHandle, path, + passphrase); break; + case "perma": + String baseUrl = JvmSettings.LEGACY_PERMALINK_BASEURL.lookup(); + legacy = new PermaLinkPidProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, + dataFilePidFormat, "", "", baseUrl, PermaLinkPidProvider.SEPARATOR); } if (legacy != null) { legacy.setPidProviderServiceBean(this); diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index 816a6607824..3240859753c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -111,6 +111,23 @@ public enum JvmSettings { LEGACY_DATACITE_USERNAME(SCOPE_LEGACY_PID_DATACITE, "username", "doi.username"), LEGACY_DATACITE_PASSWORD(SCOPE_LEGACY_PID_DATACITE, "password", "doi.password"), + // PROVIDER EZID (legacy - single provider setting) + SCOPE_LEGACY_PID_EZID(SCOPE_PID, "ezid"), + LEGACY_EZID_API_URL(SCOPE_LEGACY_PID_EZID, "api-url"), + LEGACY_EZID_USERNAME(SCOPE_LEGACY_PID_EZID, "username"), + LEGACY_EZID_PASSWORD(SCOPE_LEGACY_PID_EZID, "password"), + + // PROVIDER PERMALINK (legacy - single provider setting) + SCOPE_LEGACY_PID_PERMALINK(SCOPE_PID, "permalink"), + LEGACY_PERMALINK_BASEURL(SCOPE_LEGACY_PID_PERMALINK, "base-url", "perma.baseurlstring"), + + // PROVIDER HANDLE (legacy - single provider setting) + SCOPE_LEGACY_PID_HANDLENET(SCOPE_PID, "handlenet"), + LEGACY_HANDLENET_INDEX(SCOPE_LEGACY_PID_HANDLENET, "index", "dataverse.handlenet.index"), + SCOPE_LEGACY_PID_HANDLENET_KEY(SCOPE_LEGACY_PID_HANDLENET, "key"), + LEGACY_HANDLENET_KEY_PATH(SCOPE_LEGACY_PID_HANDLENET_KEY, "path", "dataverse.handlenet.admcredfile"), + LEGACY_HANDLENET_KEY_PASSPHRASE(SCOPE_LEGACY_PID_HANDLENET_KEY, "passphrase", "dataverse.handlenet.admprivphrase"), + // PROVIDER EZID - these settings were formerly kept together with DataCite ones SCOPE_PID_EZID(SCOPE_PID_PROVIDER, "ezid"), EZID_API_URL(SCOPE_PID_EZID, "api-url"), diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 29f17b6bcec..87c93fc2f85 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -348,7 +348,7 @@ Whether Harvesting (OAI) service is enabled PVCustomPasswordResetAlertMessage, /* String to describe DOI format for data files. Default is DEPENDENT. - 'DEPENEDENT' means the DOI will be the Dataset DOI plus a file DOI with a slash in between. + 'DEPENDENT' means the DOI will be the Dataset DOI plus a file DOI with a slash in between. 'INDEPENDENT' means a new global id, completely independent from the dataset-level global id. */ DataFilePIDFormat, @@ -367,12 +367,12 @@ Whether Harvesting (OAI) service is enabled /** * Indicates if the Handle service is setup to work 'independently' (No communication with the Global Handle Registry) */ - //IndependentHandleService, + IndependentHandleService, /** Handle to use for authentication if the default is not being used */ - //HandleAuthHandle, + HandleAuthHandle, /** * Archiving can be configured by providing an Archiver class name (class must extend AstractSubmitToArchiverCommand) From 2e777cc7efd3a08969b67cddbec34dd59680a2f4 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 9 Feb 2024 13:40:59 -0500 Subject: [PATCH 073/113] new packages for everyone! (refactor) --- .../edu/harvard/iq/dataverse/DatasetPage.java | 6 ++--- .../iq/dataverse/EjbDataverseEngine.java | 10 +++---- .../edu/harvard/iq/dataverse/GlobalId.java | 2 +- .../edu/harvard/iq/dataverse/api/Admin.java | 2 +- .../harvard/iq/dataverse/api/LDNInbox.java | 8 +++--- .../iq/dataverse/api/MakeDataCountApi.java | 2 +- .../api/imports/ImportGenericServiceBean.java | 20 +++++++------- .../impl/AbstractSubmitToArchiveCommand.java | 2 +- .../command/impl/RegisterDvObjectCommand.java | 3 ++- .../export/InternalExportDataProvider.java | 2 +- .../export/openaire/OpenAireExportUtil.java | 6 ++--- .../pidproviders/AbstractPidProvider.java | 6 ++--- .../pidproviders/PidProviderFactoryBean.java | 10 ++++++- .../iq/dataverse/pidproviders/PidUtil.java | 10 ++++--- .../AbstractDOIProvider.java} | 10 ++++--- .../{ => doi}/UnmanagedDOIProvider.java | 8 +++--- .../datacite/DOIDataCiteRegisterCache.java | 2 +- .../datacite/DOIDataCiteRegisterService.java | 3 +-- .../datacite}/DataCiteDOIProvider.java | 6 ++--- .../datacite}/DataCiteProviderFactory.java | 4 ++- .../datacite/DataCiteRESTfullClient.java | 2 +- .../{ => doi/ezid}/EZIdDOIProvider.java | 5 ++-- .../{ => doi/ezid}/EZIdProviderFactory.java | 4 ++- .../{ => doi/fake}/FakeDOIProvider.java | 7 ++--- .../{ => doi/fake}/FakeProviderFactory.java | 4 ++- .../{ => handle}/HandlePidProvider.java | 6 +++-- .../{ => handle}/HandleProviderFactory.java | 4 ++- .../UnmanagedHandlePidProvider.java | 5 ++-- .../{ => perma}/PermaLinkPidProvider.java | 4 ++- .../{ => perma}/PermaLinkProviderFactory.java | 4 ++- .../UnmanagedPermaLinkPidProvider.java | 5 ++-- .../harvard/iq/dataverse/GlobalIdTest.java | 6 ++--- .../dataaccess/GlobusOverlayAccessIOTest.java | 6 ++--- .../dataaccess/RemoteOverlayAccessIOTest.java | 4 +-- .../export/OpenAireExportUtilTest.java | 6 ++--- .../ExternalToolHandlerTest.java | 4 +-- .../ExternalToolServiceBeanTest.java | 4 +-- .../iq/dataverse/globus/GlobusUtilTest.java | 6 ++--- .../dataverse/pidproviders/PidUtilTest.java | 26 ++++++++++++++----- .../search/IndexServiceBeanTest.java | 4 +-- .../iq/dataverse/sitemap/SiteMapUtilTest.java | 10 +++---- .../iq/dataverse/util/UrlTokenUtilTest.java | 4 +-- 42 files changed, 148 insertions(+), 104 deletions(-) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{DOIProvider.java => doi/AbstractDOIProvider.java} (78%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi}/UnmanagedDOIProvider.java (89%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi}/datacite/DOIDataCiteRegisterCache.java (96%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi}/datacite/DOIDataCiteRegisterService.java (99%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi/datacite}/DataCiteDOIProvider.java (98%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi/datacite}/DataCiteProviderFactory.java (90%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi}/datacite/DataCiteRESTfullClient.java (99%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi/ezid}/EZIdDOIProvider.java (98%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi/ezid}/EZIdProviderFactory.java (89%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi/fake}/FakeDOIProvider.java (90%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi/fake}/FakeProviderFactory.java (88%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => handle}/HandlePidProvider.java (98%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => handle}/HandleProviderFactory.java (91%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => handle}/UnmanagedHandlePidProvider.java (94%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => perma}/PermaLinkPidProvider.java (97%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => perma}/PermaLinkProviderFactory.java (90%) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => perma}/UnmanagedPermaLinkPidProvider.java (95%) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index cd63f8c92a7..88b1f4f49bc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -43,10 +43,10 @@ import edu.harvard.iq.dataverse.ingest.IngestServiceBean; import edu.harvard.iq.dataverse.license.LicenseServiceBean; import edu.harvard.iq.dataverse.metadataimport.ForeignMetadataImportServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DataCiteDOIProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.privateurl.PrivateUrlUtil; @@ -6398,7 +6398,7 @@ public String getSignpostingLinkHeader() { } public boolean isDOI() { - return DOIProvider.DOI_PROTOCOL.equals(dataset.getGlobalId().getProtocol()); + return AbstractDOIProvider.DOI_PROTOCOL.equals(dataset.getGlobalId().getProtocol()); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java index b68743a15f8..aa2fb6cbebd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java +++ b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java @@ -17,12 +17,12 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.EZIdDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.FakeDOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; +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; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkPidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; diff --git a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java index 47495f9ab9f..a542cb52ac0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GlobalId.java +++ b/src/main/java/edu/harvard/iq/dataverse/GlobalId.java @@ -6,7 +6,7 @@ package edu.harvard.iq.dataverse; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkPidProvider; import edu.harvard.iq.dataverse.util.BundleUtil; import static edu.harvard.iq.dataverse.util.StringUtil.isEmpty; import java.net.MalformedURLException; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 207a88f94bb..d098c2fe16a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -97,7 +97,7 @@ import edu.harvard.iq.dataverse.engine.command.impl.DeleteTemplateCommand; import edu.harvard.iq.dataverse.engine.command.impl.RegisterDvObjectCommand; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.userdata.UserListMaker; import edu.harvard.iq.dataverse.userdata.UserListResult; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java b/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java index 403470a63e1..6a9c608dc13 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/LDNInbox.java @@ -12,9 +12,9 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.ip.IpAddress; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.json.JSONLDUtil; import edu.harvard.iq.dataverse.util.json.JsonLDNamespace; @@ -134,8 +134,8 @@ public Response acceptMessage(String body) { .getString("@id"); if (citedResource.getString("@type").equals(JsonLDTerm.schemaOrg("Dataset").getUrl())) { logger.fine("Raw PID: " + pid); - if (pid.startsWith(DOIProvider.DOI_RESOLVER_URL)) { - pid = pid.replace(DOIProvider.DOI_RESOLVER_URL, DOIProvider.DOI_PROTOCOL + ":"); + if (pid.startsWith(AbstractDOIProvider.DOI_RESOLVER_URL)) { + pid = pid.replace(AbstractDOIProvider.DOI_RESOLVER_URL, AbstractDOIProvider.DOI_PROTOCOL + ":"); } else if (pid.startsWith(HandlePidProvider.HDL_RESOLVER_URL)) { pid = pid.replace(HandlePidProvider.HDL_RESOLVER_URL, HandlePidProvider.HDL_PROTOCOL + ":"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java b/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java index 8d80b568da0..08e776a3eb8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java @@ -7,9 +7,9 @@ import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitationsServiceBean; import edu.harvard.iq.dataverse.makedatacount.DatasetMetrics; import edu.harvard.iq.dataverse.makedatacount.DatasetMetricsServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; +import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DataCiteDOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; import edu.harvard.iq.dataverse.util.json.JsonUtil; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java index ca84588b706..6068ec45e4f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java @@ -15,9 +15,9 @@ import edu.harvard.iq.dataverse.api.dto.FieldDTO; import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO; import edu.harvard.iq.dataverse.license.LicenseServiceBean; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; -import edu.harvard.iq.dataverse.pidproviders.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkPidProvider; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.StringUtil; import edu.harvard.iq.dataverse.util.json.JsonParseException; @@ -352,7 +352,7 @@ private String getOtherIdFromDTO(DatasetVersionDTO datasetVersionDTO) { if (!otherIds.isEmpty()) { // We prefer doi or hdl identifiers like "doi:10.7910/DVN/1HE30F" for (String otherId : otherIds) { - if (otherId.startsWith(DOIProvider.DOI_PROTOCOL) || otherId.startsWith(HandlePidProvider.HDL_PROTOCOL) || otherId.startsWith(DOIProvider.DOI_RESOLVER_URL) || otherId.startsWith(HandlePidProvider.HDL_RESOLVER_URL) || otherId.startsWith(DOIProvider.HTTP_DOI_RESOLVER_URL) || otherId.startsWith(HandlePidProvider.HTTP_HDL_RESOLVER_URL) || otherId.startsWith(DOIProvider.DXDOI_RESOLVER_URL) || otherId.startsWith(DOIProvider.HTTP_DXDOI_RESOLVER_URL)) { + if (otherId.startsWith(AbstractDOIProvider.DOI_PROTOCOL) || otherId.startsWith(HandlePidProvider.HDL_PROTOCOL) || otherId.startsWith(AbstractDOIProvider.DOI_RESOLVER_URL) || otherId.startsWith(HandlePidProvider.HDL_RESOLVER_URL) || otherId.startsWith(AbstractDOIProvider.HTTP_DOI_RESOLVER_URL) || otherId.startsWith(HandlePidProvider.HTTP_HDL_RESOLVER_URL) || otherId.startsWith(AbstractDOIProvider.DXDOI_RESOLVER_URL) || otherId.startsWith(AbstractDOIProvider.HTTP_DXDOI_RESOLVER_URL)) { return otherId; } } @@ -388,7 +388,7 @@ public String reassignIdentifierAsGlobalId(String identifierString, DatasetDTO d String protocol = identifierString.substring(0, index1); - if (DOIProvider.DOI_PROTOCOL.equals(protocol) || HandlePidProvider.HDL_PROTOCOL.equals(protocol) || PermaLinkPidProvider.PERMA_PROTOCOL.equals(protocol)) { + if (AbstractDOIProvider.DOI_PROTOCOL.equals(protocol) || HandlePidProvider.HDL_PROTOCOL.equals(protocol) || PermaLinkPidProvider.PERMA_PROTOCOL.equals(protocol)) { logger.fine("Processing hdl:- or doi:- or perma:-style identifier : "+identifierString); } else if ("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) { @@ -401,12 +401,12 @@ public String reassignIdentifierAsGlobalId(String identifierString, DatasetDTO d protocol = HandlePidProvider.HDL_PROTOCOL; index1 = (identifierString.startsWith(HandlePidProvider.HDL_RESOLVER_URL)) ? HandlePidProvider.HDL_RESOLVER_URL.length() - 1 : HandlePidProvider.HTTP_HDL_RESOLVER_URL.length() - 1; index2 = identifierString.indexOf("/", index1 + 1); - } else if (identifierString.startsWith(DOIProvider.DOI_RESOLVER_URL) || identifierString.startsWith(DOIProvider.HTTP_DOI_RESOLVER_URL) || identifierString.startsWith(DOIProvider.DXDOI_RESOLVER_URL) || identifierString.startsWith(DOIProvider.HTTP_DXDOI_RESOLVER_URL)) { + } else if (identifierString.startsWith(AbstractDOIProvider.DOI_RESOLVER_URL) || identifierString.startsWith(AbstractDOIProvider.HTTP_DOI_RESOLVER_URL) || identifierString.startsWith(AbstractDOIProvider.DXDOI_RESOLVER_URL) || identifierString.startsWith(AbstractDOIProvider.HTTP_DXDOI_RESOLVER_URL)) { logger.fine("Processing DOI identifier formatted as a resolver URL: "+identifierString); - protocol = DOIProvider.DOI_PROTOCOL; - identifierString = identifierString.replace(DOIProvider.DXDOI_RESOLVER_URL, DOIProvider.DOI_RESOLVER_URL); - identifierString = identifierString.replace(DOIProvider.HTTP_DXDOI_RESOLVER_URL, DOIProvider.HTTP_DOI_RESOLVER_URL); - index1 = (identifierString.startsWith(DOIProvider.DOI_RESOLVER_URL)) ? DOIProvider.DOI_RESOLVER_URL.length() - 1 : DOIProvider.HTTP_DOI_RESOLVER_URL.length() - 1; + protocol = AbstractDOIProvider.DOI_PROTOCOL; + identifierString = identifierString.replace(AbstractDOIProvider.DXDOI_RESOLVER_URL, AbstractDOIProvider.DOI_RESOLVER_URL); + identifierString = identifierString.replace(AbstractDOIProvider.HTTP_DXDOI_RESOLVER_URL, AbstractDOIProvider.HTTP_DOI_RESOLVER_URL); + index1 = (identifierString.startsWith(AbstractDOIProvider.DOI_RESOLVER_URL)) ? AbstractDOIProvider.DOI_RESOLVER_URL.length() - 1 : AbstractDOIProvider.HTTP_DOI_RESOLVER_URL.length() - 1; index2 = identifierString.indexOf("/", index1 + 1); } else if (identifierString.startsWith(PermaLinkPidProvider.PERMA_RESOLVER_URL + Dataset.TARGET_URL)) { protocol = PermaLinkPidProvider.PERMA_PROTOCOL; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java index 4eeb36ed254..29c27d0396d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractSubmitToArchiveCommand.java @@ -13,7 +13,7 @@ import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; -import edu.harvard.iq.dataverse.pidproviders.datacite.DOIDataCiteRegisterService; +import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DOIDataCiteRegisterService; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.bagit.BagGenerator; import edu.harvard.iq.dataverse.util.bagit.OREMap; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java index a2fe8413d9d..7b80871a1e0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/RegisterDvObjectCommand.java @@ -10,8 +10,9 @@ import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; + import java.sql.Timestamp; import java.util.Date; diff --git a/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java b/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java index 9edb456c890..f0d77eb8b52 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/InternalExportDataProvider.java @@ -12,7 +12,7 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; -import edu.harvard.iq.dataverse.pidproviders.datacite.DOIDataCiteRegisterService; +import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DOIDataCiteRegisterService; import io.gdcc.spi.export.ExportDataProvider; import edu.harvard.iq.dataverse.util.bagit.OREMap; import edu.harvard.iq.dataverse.util.json.JsonPrinter; diff --git a/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java b/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java index 6cc4210e6a9..49ceabc5900 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/openaire/OpenAireExportUtil.java @@ -20,9 +20,9 @@ import edu.harvard.iq.dataverse.api.dto.FieldDTO; import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO; import edu.harvard.iq.dataverse.util.PersonOrOrgUtil; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; import edu.harvard.iq.dataverse.util.json.JsonUtil; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -189,7 +189,7 @@ public static void writeIdentifierElement(XMLStreamWriter xmlw, String identifie if (StringUtils.isNotBlank(identifier)) { Map identifier_map = new HashMap(); - if (StringUtils.containsIgnoreCase(identifier, DOIProvider.DOI_RESOLVER_URL)) { + if (StringUtils.containsIgnoreCase(identifier, AbstractDOIProvider.DOI_RESOLVER_URL)) { identifier_map.put("identifierType", "DOI"); identifier = StringUtils.substring(identifier, identifier.indexOf("10.")); } else if (StringUtils.containsIgnoreCase(identifier, HandlePidProvider.HDL_RESOLVER_URL)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index f75132e6697..9b98c57e807 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -32,7 +32,7 @@ public abstract class AbstractPidProvider implements PidProvider { public static String UNAVAILABLE = ":unav"; public static final String SEPARATOR = "/"; - PidProviderFactoryBean pidProviderService; + protected PidProviderFactoryBean pidProviderService; private String protocol; @@ -51,7 +51,7 @@ public abstract class AbstractPidProvider implements PidProvider { private String id; private String label; - AbstractPidProvider(String id, String label, String protocol) { + protected AbstractPidProvider(String id, String label, String protocol) { this.id = id; this.label = label; this.protocol = protocol; @@ -59,7 +59,7 @@ public abstract class AbstractPidProvider implements PidProvider { this.excludedSet = new HashSet(); } - AbstractPidProvider(String id, String label, String protocol, String authority, String shoulder, + protected AbstractPidProvider(String id, String label, String protocol, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { this.id = id; this.label = label; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index ee7093aa6bb..d8d8a95c195 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -29,6 +29,14 @@ import edu.harvard.iq.dataverse.DataverseServiceBean; 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.datacite.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.ezid.EZIdDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.fake.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.UnmanagedHandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.UnmanagedPermaLinkPidProvider; /** * This Bean loads all of the PidProviderFactory types available (e.g. EZID, @@ -203,7 +211,7 @@ String getProducer() { return dataverseService.getRootDataverseName(); } - boolean isGlobalIdLocallyUnique(GlobalId globalId) { + public boolean isGlobalIdLocallyUnique(GlobalId globalId) { return dvObjectService.isGlobalIdLocallyUnique(globalId); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java index bbf56cdfe83..279f18dcd0e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidUtil.java @@ -1,6 +1,8 @@ package edu.harvard.iq.dataverse.pidproviders; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; import edu.harvard.iq.dataverse.util.BundleUtil; import java.io.IOException; import java.io.InputStream; @@ -111,7 +113,7 @@ public static JsonObjectBuilder queryDoi(GlobalId globalId, String baseUrl, Stri * @return DOI in the form 10.7910/DVN/TJCLKP (no "doi:") */ private static String acceptOnlyDoi(GlobalId globalId) { - if (!DOIProvider.DOI_PROTOCOL.equals(globalId.getProtocol())) { + if (!AbstractDOIProvider.DOI_PROTOCOL.equals(globalId.getProtocol())) { throw new IllegalArgumentException(BundleUtil.getStringFromBundle("pids.datacite.errors.DoiOnly")); } return globalId.getAuthority() + "/" + globalId.getIdentifier(); @@ -187,7 +189,7 @@ public static GlobalId parseAsGlobalID(String protocol, String authority, String * This method should be deprecated/removed when further refactoring to support * multiple PID providers is done. At that point, when the providers aren't * beans, this code can be moved into other classes that go in the providerMap. - * If this method is not kept in sync with the DOIProvider and HandlePidProvider + * If this method is not kept in sync with the AbstractDOIProvider and HandlePidProvider * implementations, the tests using it won't be valid tests of the production * code. */ @@ -199,11 +201,11 @@ private static GlobalId parseUnmanagedDoiOrHandle(String protocol, String author } String urlPrefix = null; switch (protocol) { - case DOIProvider.DOI_PROTOCOL: + case AbstractDOIProvider.DOI_PROTOCOL: if (!PidProvider.checkDOIAuthority(authority)) { return null; } - urlPrefix = DOIProvider.DOI_RESOLVER_URL; + urlPrefix = AbstractDOIProvider.DOI_RESOLVER_URL; break; case HandlePidProvider.HDL_PROTOCOL: urlPrefix = HandlePidProvider.HDL_RESOLVER_URL; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java similarity index 78% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java index ddd8f29f792..7a0ea052fb3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java @@ -1,9 +1,11 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; -public abstract class DOIProvider extends AbstractPidProvider { +public abstract class AbstractDOIProvider extends AbstractPidProvider { public static final String DOI_PROTOCOL = "doi"; public static final String DOI_RESOLVER_URL = "https://doi.org/"; @@ -11,12 +13,12 @@ public abstract class DOIProvider extends AbstractPidProvider { public static final String DXDOI_RESOLVER_URL = "https://dx.doi.org/"; public static final String HTTP_DXDOI_RESOLVER_URL = "http://dx.doi.org/"; - public DOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { + public AbstractDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { super(id, label, DOI_PROTOCOL, providerAuthority, providerShoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); } //For Unmanged provider - public DOIProvider(String name, String label) { + public AbstractDOIProvider(String name, String label) { super(name, label, DOI_PROTOCOL); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/UnmanagedDOIProvider.java similarity index 89% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/UnmanagedDOIProvider.java index ebb76e00181..d4e674f8396 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/UnmanagedDOIProvider.java @@ -1,4 +1,4 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi; import java.io.IOException; import java.util.List; @@ -14,9 +14,9 @@ * */ -public class UnmanagedDOIProvider extends DOIProvider { +public class UnmanagedDOIProvider extends AbstractDOIProvider { - static final String ID = "UnmanagedDOIProvider"; + public static final String ID = "UnmanagedDOIProvider"; public UnmanagedDOIProvider() { //Also using ID as label @@ -74,6 +74,6 @@ public String getProviderType() { } // PID recognition - // Done by DOIProvider + // Done by AbstractDOIProvider } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterCache.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java similarity index 96% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterCache.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java index 32cef08b4f7..4d296282c91 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterCache.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse.pidproviders.datacite; +package edu.harvard.iq.dataverse.pidproviders.doi.datacite; import java.io.Serializable; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java similarity index 99% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java index e4b2231b2c9..100f6e11aed 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse.pidproviders.datacite; +package edu.harvard.iq.dataverse.pidproviders.doi.datacite; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; @@ -13,7 +13,6 @@ import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; -import edu.harvard.iq.dataverse.pidproviders.DataCiteDOIProvider; import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider.GlobalIdMetadataTemplate; import java.io.ByteArrayOutputStream; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java similarity index 98% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java index 8ba6d082e67..4cbfbc7cc14 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java @@ -1,4 +1,4 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi.datacite; import java.io.IOException; import java.net.HttpURLConnection; @@ -15,7 +15,7 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; -import edu.harvard.iq.dataverse.pidproviders.datacite.DOIDataCiteRegisterService; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; @@ -24,7 +24,7 @@ * * @author luopc */ -public class DataCiteDOIProvider extends DOIProvider { +public class DataCiteDOIProvider extends AbstractDOIProvider { private static final Logger logger = Logger.getLogger(DataCiteDOIProvider.class.getCanonicalName()); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderFactory.java similarity index 90% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderFactory.java index f43c0f41bea..99d13b2647c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/DataCiteProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderFactory.java @@ -1,7 +1,9 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi.datacite; 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; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DataCiteRESTfullClient.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java similarity index 99% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DataCiteRESTfullClient.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java index 2c4e94c1f79..771aa781876 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/datacite/DataCiteRESTfullClient.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package edu.harvard.iq.dataverse.pidproviders.datacite; +package edu.harvard.iq.dataverse.pidproviders.doi.datacite; import java.io.Closeable; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java similarity index 98% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java index cedf0b4d204..75e88de0d34 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java @@ -1,9 +1,10 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi.ezid; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.ucsb.nceas.ezid.EZIDException; import edu.ucsb.nceas.ezid.EZIDService; @@ -17,7 +18,7 @@ * * @author skraffmiller */ -public class EZIdDOIProvider extends DOIProvider { +public class EZIdDOIProvider extends AbstractDOIProvider { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java similarity index 89% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java index bb4ab1392e7..6c9e6f06c6f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java @@ -1,7 +1,9 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi.ezid; 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; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/fake/FakeDOIProvider.java similarity index 90% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/fake/FakeDOIProvider.java index cf8f0951b53..a967fb40620 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/fake/FakeDOIProvider.java @@ -1,15 +1,16 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi.fake; 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; -public class FakeDOIProvider extends DOIProvider { +public class FakeDOIProvider extends AbstractDOIProvider { - static final String TYPE = "FAKE"; + public static final String TYPE = "FAKE"; public FakeDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList) { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/fake/FakeProviderFactory.java similarity index 88% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/fake/FakeProviderFactory.java index 95d512aca48..292c39d4383 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakeProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/fake/FakeProviderFactory.java @@ -1,7 +1,9 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi.fake; 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; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandlePidProvider.java similarity index 98% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandlePidProvider.java index ed248375933..2627bc76fd9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandlePidProvider.java @@ -18,11 +18,13 @@ Version 3.0. */ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.handle; import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; + import java.io.File; import java.io.FileInputStream; import java.nio.charset.StandardCharsets; @@ -75,7 +77,7 @@ public class HandlePidProvider extends AbstractPidProvider { private String keyPath; private String keyPassphrase; - HandlePidProvider(String id, String label, String authority, String shoulder, String identifierGenerationStyle, + public HandlePidProvider(String id, String label, String authority, String shoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, int index, boolean isIndependentService, String authHandle, String path, String passphrase) { super(id, label, HDL_PROTOCOL, authority, shoulder, identifierGenerationStyle, datafilePidFormat, managedList, excludedList); this.handlenetIndex = index; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java similarity index 91% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java index be3c7a94c37..9dd1c5f2928 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java @@ -1,7 +1,9 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.handle; 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; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/UnmanagedHandlePidProvider.java similarity index 94% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/UnmanagedHandlePidProvider.java index b292785632a..075e10d8164 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedHandlePidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/UnmanagedHandlePidProvider.java @@ -1,7 +1,8 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.handle; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; import java.util.*; import java.util.logging.Level; @@ -19,7 +20,7 @@ public class UnmanagedHandlePidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedHandlePidProvider.class.getCanonicalName()); - static final String ID = "UnmanagedHandleProvider"; + public static final String ID = "UnmanagedHandleProvider"; public UnmanagedHandlePidProvider() { // Also using ID as label diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/PermaLinkPidProvider.java similarity index 97% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/PermaLinkPidProvider.java index 0a28fb0d5f1..91c7f527c88 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/PermaLinkPidProvider.java @@ -1,7 +1,9 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.perma; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; +import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.SystemConfig; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/PermaLinkProviderFactory.java similarity index 90% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/PermaLinkProviderFactory.java index 13b4de540cb..32b89223062 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PermaLinkProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/PermaLinkProviderFactory.java @@ -1,7 +1,9 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.perma; 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; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/UnmanagedPermaLinkPidProvider.java similarity index 95% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/UnmanagedPermaLinkPidProvider.java index bfe43bd9448..b7961a41c50 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/UnmanagedPermaLinkPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/perma/UnmanagedPermaLinkPidProvider.java @@ -1,7 +1,8 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.perma; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; import edu.harvard.iq.dataverse.util.SystemConfig; import java.util.*; @@ -17,7 +18,7 @@ public class UnmanagedPermaLinkPidProvider extends AbstractPidProvider { private static final Logger logger = Logger.getLogger(UnmanagedPermaLinkPidProvider.class.getCanonicalName()); - static final String ID = "UnmanagedPermaLinkProvider"; + public static final String ID = "UnmanagedPermaLinkProvider"; public UnmanagedPermaLinkPidProvider() { // Also using ID as label diff --git a/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java b/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java index 96c6228f386..7065e9689e1 100644 --- a/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/GlobalIdTest.java @@ -3,9 +3,9 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -21,7 +21,7 @@ public class GlobalIdTest { @Test public void testValidDOI() { System.out.println("testValidDOI"); - GlobalId instance = new GlobalId(DOIProvider.DOI_PROTOCOL,"10.5072","FK2/BYM3IW", "/", DOIProvider.DOI_RESOLVER_URL, null); + GlobalId instance = new GlobalId(AbstractDOIProvider.DOI_PROTOCOL,"10.5072","FK2/BYM3IW", "/", AbstractDOIProvider.DOI_RESOLVER_URL, null); assertEquals("doi", instance.getProtocol()); assertEquals("10.5072", instance.getAuthority()); diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java index 8993566b7ab..d173f65757f 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/GlobusOverlayAccessIOTest.java @@ -7,7 +7,7 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.mocks.MocksFactory; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -94,8 +94,8 @@ public static void tearDown() { void testGlobusOverlayIdentifiers() throws IOException { dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, authority, identifier, "/", - DOIProvider.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, authority, identifier, "/", + AbstractDOIProvider.DOI_RESOLVER_URL, null)); mDatafile = MocksFactory.makeDataFile(); mDatafile.setOwner(dataset); mDatafile.setStorageIdentifier("globusm://" + baseStoreId1); diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java index 90c7595a5e0..2c0e0a5c6b7 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/RemoteOverlayAccessIOTest.java @@ -8,7 +8,7 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.mocks.MocksFactory; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.util.UrlSignerUtil; import org.junit.jupiter.api.AfterEach; @@ -50,7 +50,7 @@ public void setUp() { System.setProperty("dataverse.files.file.label", "default"); datafile = MocksFactory.makeDataFile(); dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, authority, identifier, "/", DOIProvider.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, authority, identifier, "/", AbstractDOIProvider.DOI_RESOLVER_URL, null)); datafile.setOwner(dataset); datafile.setStorageIdentifier("test://" + baseStoreId + "//" + logoPath); diff --git a/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java index 8ca5b235256..8c40bfcee85 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/export/OpenAireExportUtilTest.java @@ -11,8 +11,8 @@ import edu.harvard.iq.dataverse.api.dto.DatasetDTO; import edu.harvard.iq.dataverse.api.dto.DatasetVersionDTO; import edu.harvard.iq.dataverse.export.openaire.OpenAireExportUtil; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; -import edu.harvard.iq.dataverse.pidproviders.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; import java.io.IOException; import java.io.StringWriter; @@ -57,7 +57,7 @@ public void testWriteIdentifierElementDoi() throws XMLStreamException { String persistentAgency = "doi"; String persistentAuthority = "10.123"; String persistentId = "123"; - GlobalId globalId = new GlobalId(persistentAgency, persistentAuthority, persistentId, null, DOIProvider.DOI_RESOLVER_URL, null); + GlobalId globalId = new GlobalId(persistentAgency, persistentAuthority, persistentId, null, AbstractDOIProvider.DOI_RESOLVER_URL, null); // when OpenAireExportUtil.writeIdentifierElement(xmlWriter, globalId.asURL(), null); diff --git a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java index e90573a52a9..639a7c542c4 100644 --- a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolHandlerTest.java @@ -8,7 +8,7 @@ import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.users.ApiToken; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.URLTokenUtil; import edu.harvard.iq.dataverse.util.json.JsonUtil; @@ -267,7 +267,7 @@ public void testDatasetConfigureTool() { .build().toString()); var dataset = new Dataset(); - dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.5072", "ABC123", null, DOIProvider.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, "10.5072", "ABC123", null, AbstractDOIProvider.DOI_RESOLVER_URL, null)); ApiToken nullApiToken = null; String nullLocaleCode = "en"; var externalToolHandler = new ExternalToolHandler(externalTool, dataset, nullApiToken, nullLocaleCode); diff --git a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java index 606afba9b04..bb39aecfa79 100644 --- a/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/externaltools/ExternalToolServiceBeanTest.java @@ -8,7 +8,7 @@ import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.users.ApiToken; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.util.URLTokenUtil; import java.util.ArrayList; @@ -144,7 +144,7 @@ public void testParseAddFileToolFilePid() { assertEquals("explorer", externalTool.getToolName()); DataFile dataFile = new DataFile(); dataFile.setId(42l); - dataFile.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL,"10.5072","FK2/RMQT6J/G9F1A1", "/", DOIProvider.DOI_RESOLVER_URL, null)); + dataFile.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL,"10.5072","FK2/RMQT6J/G9F1A1", "/", AbstractDOIProvider.DOI_RESOLVER_URL, null)); FileMetadata fmd = new FileMetadata(); fmd.setId(2L); DatasetVersion dv = new DatasetVersion(); diff --git a/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java index 95e391071bc..095e798f229 100644 --- a/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/globus/GlobusUtilTest.java @@ -20,7 +20,7 @@ import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.GlobusAccessibleStore; import edu.harvard.iq.dataverse.mocks.MocksFactory; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.util.json.JsonUtil; import jakarta.json.JsonObject; @@ -52,8 +52,8 @@ public void setUp() { "d7c42580-6538-4605-9ad8-116a61982644/hdc1"); dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, authority, identifier, "/", - DOIProvider.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, authority, identifier, "/", + AbstractDOIProvider.DOI_RESOLVER_URL, null)); mDatafile = MocksFactory.makeDataFile(); mDatafile.setOwner(dataset); mDatafile.setStorageIdentifier("globusm://" + baseStoreId1); diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java index 52706378438..dc226d2e85b 100644 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidUtilTest.java @@ -3,6 +3,20 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.UnmanagedDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DataCiteDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.datacite.DataCiteProviderFactory; +import edu.harvard.iq.dataverse.pidproviders.doi.ezid.EZIdDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.ezid.EZIdProviderFactory; +import edu.harvard.iq.dataverse.pidproviders.doi.fake.FakeDOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.fake.FakeProviderFactory; +import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.handle.HandleProviderFactory; +import edu.harvard.iq.dataverse.pidproviders.handle.UnmanagedHandlePidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkPidProvider; +import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkProviderFactory; +import edu.harvard.iq.dataverse.pidproviders.perma.UnmanagedPermaLinkPidProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; @@ -156,7 +170,7 @@ public void testGetDoi() throws IOException { String username = System.getenv("DataCiteUsername"); String password = System.getenv("DataCitePassword"); String baseUrl = "https://api.test.datacite.org"; - GlobalId pid = new GlobalId(DOIProvider.DOI_PROTOCOL,"10.70122","QE5A-XN55", "/", DOIProvider.DOI_RESOLVER_URL, null); + GlobalId pid = new GlobalId(AbstractDOIProvider.DOI_PROTOCOL,"10.70122","QE5A-XN55", "/", AbstractDOIProvider.DOI_RESOLVER_URL, null); try { JsonObjectBuilder result = PidUtil.queryDoi(pid, baseUrl, username, password); String out = JsonUtil.prettyPrint(result.build()); @@ -218,7 +232,7 @@ public void testDOIParsing() throws IOException { assertEquals("dc1", pid2.getProviderId()); assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); assertEquals("10.5073", pid2.getAuthority()); - assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); + assertEquals(AbstractDOIProvider.DOI_PROTOCOL, pid2.getProtocol()); GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); assertEquals(pid1String, pid3.asString()); assertEquals("dc1", pid3.getProviderId()); @@ -294,7 +308,7 @@ public void testExcludedSetParsing() throws IOException { assertEquals(UnmanagedDOIProvider.ID, pid2.getProviderId()); assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); assertEquals("10.5073", pid2.getAuthority()); - assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); + assertEquals(AbstractDOIProvider.DOI_PROTOCOL, pid2.getProtocol()); GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); assertEquals(pid1String, pid3.asString()); assertEquals(UnmanagedDOIProvider.ID, pid3.getProviderId()); @@ -326,7 +340,7 @@ public void testManagedSetParsing() throws IOException { assertEquals("fake1", pid2.getProviderId()); assertEquals("https://doi.org/" + pid2.getAuthority() + PidUtil.getPidProvider(pid2.getProviderId()).getSeparator() + pid2.getIdentifier(),pid2.asURL()); assertEquals("10.5073", pid2.getAuthority()); - assertEquals(DOIProvider.DOI_PROTOCOL, pid2.getProtocol()); + assertEquals(AbstractDOIProvider.DOI_PROTOCOL, pid2.getProtocol()); GlobalId pid3 = PidUtil.parseAsGlobalID(pid2.asURL()); assertEquals(pid1String, pid3.asString()); assertEquals("fake1", pid3.getProviderId()); @@ -351,7 +365,7 @@ public void testFindingPidGenerators() throws IOException { Dataset dataset1 = new Dataset(); Dataverse dataverse1 = new Dataverse(); dataset1.setOwner(dataverse1); - String pidGeneratorSpecs = Json.createObjectBuilder().add("protocol", DOIProvider.DOI_PROTOCOL).add("authority","10.5072").add("shoulder", "FK2").build().toString(); + String pidGeneratorSpecs = Json.createObjectBuilder().add("protocol", AbstractDOIProvider.DOI_PROTOCOL).add("authority","10.5072").add("shoulder", "FK2").build().toString(); //Set a PID generator on the parent dataverse1.setPidGeneratorSpecs(pidGeneratorSpecs); assertEquals(pidGeneratorSpecs, dataverse1.getPidGeneratorSpecs()); @@ -360,7 +374,7 @@ public void testFindingPidGenerators() throws IOException { assertEquals("ez1", dataset1.getEffectivePidGenerator().getId()); //Change dataset to have a provider and verify that it is used instead of any effective one dataset1.setAuthority("10.5073"); - dataset1.setProtocol(DOIProvider.DOI_PROTOCOL); + dataset1.setProtocol(AbstractDOIProvider.DOI_PROTOCOL); dataset1.setIdentifier("FK2ABCDEF"); //Reset to get rid of cached @transient value dataset1.setPidGenerator(null); diff --git a/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java index c0e592e3194..92b06e5936f 100644 --- a/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/search/IndexServiceBeanTest.java @@ -4,7 +4,7 @@ import edu.harvard.iq.dataverse.Dataverse.DataverseType; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.mocks.MocksFactory; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.SystemConfig; @@ -135,7 +135,7 @@ private DatasetField constructBoundingBoxValue(String datasetFieldTypeName, Stri private IndexableDataset createIndexableDataset() { final Dataset dataset = MocksFactory.makeDataset(); - dataset.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL,"10.666", "FAKE/fake", "/", DOIProvider.DOI_RESOLVER_URL, null)); + dataset.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL,"10.666", "FAKE/fake", "/", AbstractDOIProvider.DOI_RESOLVER_URL, null)); final DatasetVersion datasetVersion = dataset.getCreateVersion(null); DatasetField field = createCVVField("language", "English", false); datasetVersion.getDatasetFields().add(field); diff --git a/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java index c61c1ebc75d..310bec72c2e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/sitemap/SiteMapUtilTest.java @@ -5,7 +5,7 @@ import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.harvest.client.HarvestingClient; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.util.xml.XmlPrinter; import edu.harvard.iq.dataverse.util.xml.XmlValidator; import java.io.File; @@ -66,14 +66,14 @@ void testUpdateSiteMap() throws IOException, ParseException, SAXException { List datasets = new ArrayList<>(); Dataset published = new Dataset(); - published.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/published1", null, DOIProvider.DOI_RESOLVER_URL, null)); + published.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, "10.666", "FAKE/published1", null, AbstractDOIProvider.DOI_RESOLVER_URL, null)); String publishedPid = published.getGlobalId().asString(); published.setPublicationDate(new Timestamp(new Date().getTime())); published.setModificationTime(new Timestamp(new Date().getTime())); datasets.add(published); Dataset unpublished = new Dataset(); - unpublished.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/unpublished1", null, DOIProvider.DOI_RESOLVER_URL, null)); + unpublished.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, "10.666", "FAKE/unpublished1", null, AbstractDOIProvider.DOI_RESOLVER_URL, null)); String unpublishedPid = unpublished.getGlobalId().asString(); Timestamp nullPublicationDateToIndicateNotPublished = null; @@ -81,14 +81,14 @@ void testUpdateSiteMap() throws IOException, ParseException, SAXException { datasets.add(unpublished); Dataset harvested = new Dataset(); - harvested.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/harvested1", null, DOIProvider.DOI_RESOLVER_URL, null)); + harvested.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, "10.666", "FAKE/harvested1", null, AbstractDOIProvider.DOI_RESOLVER_URL, null)); String harvestedPid = harvested.getGlobalId().asString(); harvested.setPublicationDate(new Timestamp(new Date().getTime())); harvested.setHarvestedFrom(new HarvestingClient()); datasets.add(harvested); Dataset deaccessioned = new Dataset(); - deaccessioned.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL, "10.666", "FAKE/deaccessioned1", null, DOIProvider.DOI_RESOLVER_URL, null)); + deaccessioned.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL, "10.666", "FAKE/deaccessioned1", null, AbstractDOIProvider.DOI_RESOLVER_URL, null)); String deaccessionedPid = deaccessioned.getGlobalId().asString(); deaccessioned.setPublicationDate(new Timestamp(new Date().getTime())); diff --git a/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java index c8bb6c99ac2..15905c2971b 100644 --- a/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/util/UrlTokenUtilTest.java @@ -6,7 +6,7 @@ import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.authorization.users.ApiToken; -import edu.harvard.iq.dataverse.pidproviders.DOIProvider; +import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.util.testing.JvmSetting; import edu.harvard.iq.dataverse.util.testing.LocalJvmSettings; @@ -32,7 +32,7 @@ void testGetToolUrlWithOptionalQueryParameters() { DatasetVersion dv = new DatasetVersion(); Dataset ds = new Dataset(); ds.setId(50L); - ds.setGlobalId(new GlobalId(DOIProvider.DOI_PROTOCOL,"10.5072","FK2ABCDEF",null, DOIProvider.DOI_RESOLVER_URL, null)); + ds.setGlobalId(new GlobalId(AbstractDOIProvider.DOI_PROTOCOL,"10.5072","FK2ABCDEF",null, AbstractDOIProvider.DOI_RESOLVER_URL, null)); dv.setDataset(ds); fmd.setDatasetVersion(dv); List fmdl = new ArrayList<>(); From e57a508f685d943bd16d0eaf6d173c0ec3b7fa47 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 9 Feb 2024 13:42:23 -0500 Subject: [PATCH 074/113] unused imports --- .../java/edu/harvard/iq/dataverse/EjbDataverseEngine.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java index aa2fb6cbebd..3793b6eeeb4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java +++ b/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java @@ -18,11 +18,6 @@ import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.ingest.IngestServiceBean; import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; -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; -import edu.harvard.iq.dataverse.pidproviders.handle.HandlePidProvider; -import edu.harvard.iq.dataverse.pidproviders.perma.PermaLinkPidProvider; import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.search.IndexBatchServiceBean; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -53,7 +48,6 @@ import static jakarta.ejb.TransactionAttributeType.SUPPORTS; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; /** From bd3c07c039649402a1d0767c5df2d8528e54f91f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 9 Feb 2024 14:44:30 -0500 Subject: [PATCH 075/113] fix cut/paste issues --- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index d8d8a95c195..6f57de9ac31 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -75,9 +75,9 @@ private void loadProviderFactories() { List jarUrls = new ArrayList<>(); Optional providerPathSetting = JvmSettings.PROVIDERS_DIRECTORY.lookupOptional(String.class); if (providerPathSetting.isPresent()) { - Path exporterDir = Paths.get(providerPathSetting.get()); + Path providersDir = Paths.get(providerPathSetting.get()); // Get all JAR files from the configured directory - try (DirectoryStream stream = Files.newDirectoryStream(exporterDir, "*.jar")) { + try (DirectoryStream stream = Files.newDirectoryStream(providersDir, "*.jar")) { // Using the foreach loop here to enable catching the URI/URL exceptions for (Path path : stream) { logger.log(Level.FINE, "Adding {0}", path.toUri().toURL()); @@ -86,7 +86,7 @@ private void loadProviderFactories() { jarUrls.add(new URL("jar:" + path.toUri().toURL() + "!/")); } } catch (IOException e) { - logger.warning("Problem accessing external Exporters: " + e.getLocalizedMessage()); + logger.warning("Problem accessing external Providers: " + e.getLocalizedMessage()); } } URLClassLoader cl = URLClassLoader.newInstance(jarUrls.toArray(new URL[0]), this.getClass().getClassLoader()); @@ -106,7 +106,7 @@ private void loadProviderFactories() { loader.forEach(providerFactory -> { String type = providerFactory.getType(); logger.fine("Loaded PidProviderFactory of type: " + type); - // If no entry for this providerName yet or if it is an external exporter + // If no entry for this providerName yet or if it is an external provider if (!pidProviderFactoryMap.containsKey(type) || providerFactory.getClass().getClassLoader().equals(cl)) { logger.fine("Adding PidProviderFactory of type: " + type + " to the map"); pidProviderFactoryMap.put(type, providerFactory); From 757d2f0914ebd28689ef3c234899ecdf195e4fd5 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 9 Feb 2024 14:53:50 -0500 Subject: [PATCH 076/113] add deprecation info --- .../java/edu/harvard/iq/dataverse/DvObjectServiceBean.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java index b37088afbc8..bd7fbeaff10 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java @@ -395,12 +395,13 @@ public String generateNewIdentifierByStoredProcedure() { return (String) query.getOutputParameterValue(1); } - /** Backward-compatibility method to get the effective pid generator for a DvObjectContainer. + /** @deprecated Backward-compatibility method to get the effective pid generator for a DvObjectContainer. * If the dvObjectContainer method fails, this method will check for the old global default settings. - * - * If/when those are no longer supported, this method can be removed. + * If/when those are no longer supported, this method can be removed and replaced with calls directly + * to dvObjectContainer.getEffectivePidGenerator(); * */ + @Deprecated(forRemoval = true, since = "2024-02-09") public PidProvider getEffectivePidGenerator(DvObjectContainer dvObjectContainer) { PidProvider pidGenerator = dvObjectContainer.getEffectivePidGenerator(); if (pidGenerator == null) { From 2e41b9e42f9f8c74eadf124538080827836a39c4 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 9 Feb 2024 14:56:56 -0500 Subject: [PATCH 077/113] Apply suggestions from code review Co-authored-by: Oliver Bertuch --- .../iq/dataverse/pidproviders/PidProviderFactory.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java index 570c52a6cdf..a7ca5257924 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java @@ -5,5 +5,11 @@ public interface PidProviderFactory { public String getType(); public PidProvider createPidProvider(String id); - + + /** + * Get ordinal value to ensure loading order of provider factories is coherent + */ + default int getOrdinal() { + return 100; + } } From 71f7c41e4ad5a6fae1357712455a11596ef0b37c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 12:31:23 -0500 Subject: [PATCH 078/113] reorg/update imports --- .../datacite/DOIDataCiteRegisterService.java | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java index 100f6e11aed..7ac8d6e48e3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java @@ -5,20 +5,10 @@ */ package edu.harvard.iq.dataverse.pidproviders.doi.datacite; -import edu.harvard.iq.dataverse.DataFile; -import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.DatasetAuthor; -import edu.harvard.iq.dataverse.DatasetField; -import edu.harvard.iq.dataverse.DataverseServiceBean; -import edu.harvard.iq.dataverse.DvObject; -import edu.harvard.iq.dataverse.branding.BrandingUtil; -import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; -import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider.GlobalIdMetadataTemplate; - -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -26,20 +16,27 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import jakarta.ejb.EJB; -import jakarta.ejb.Stateless; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.persistence.TypedQuery; -import edu.harvard.iq.dataverse.settings.JvmSettings; import org.apache.commons.text.StringEscapeUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -import java.nio.charset.StandardCharsets; +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetAuthor; +import edu.harvard.iq.dataverse.DatasetField; +import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.branding.BrandingUtil; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; +import edu.harvard.iq.dataverse.settings.JvmSettings; +import jakarta.ejb.EJB; +import jakarta.ejb.Stateless; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.TypedQuery; /** * From 7b83f3e1b38a4e8e929de32d2f5b5777a51869bb Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 12:32:24 -0500 Subject: [PATCH 079/113] revert 2e41b9e --- .../pidproviders/PidProviderFactory.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java index a7ca5257924..f7c1a4b9174 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactory.java @@ -1,15 +1,8 @@ package edu.harvard.iq.dataverse.pidproviders; public interface PidProviderFactory { - - public String getType(); - - public PidProvider createPidProvider(String id); - - /** - * Get ordinal value to ensure loading order of provider factories is coherent - */ - default int getOrdinal() { - return 100; - } + + String getType(); + + PidProvider createPidProvider(String id); } From ca49f8db9c6f81dbdb108344b3f3f6c83b7d3dd3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 13:04:40 -0500 Subject: [PATCH 080/113] deprecate old settings --- .../settings/SettingsServiceBean.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 87c93fc2f85..35db5ea7eac 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -87,6 +87,15 @@ public enum Key { * StorageSite database table. */ LocalDataAccessPath, + /** + * The algorithm used to generate PIDs, randomString (default) or + * storedProcedure + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") IdentifierGenerationStyle, OAuth2CallbackUrl, DefaultAuthProvider, @@ -189,19 +198,42 @@ public enum Key { SignUpUrl, /** Key for whether we allow users to sign up */ AllowSignUp, - /** protocol for global id */ + /** + * protocol for global id + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") Protocol, - /** authority for global id */ + /** + * authority for global id + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") Authority, - /** DoiProvider for global id */ + /** + * DoiProvider for global id + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") DoiProvider, - /** Shoulder for global id - used to create a common prefix on identifiers */ + /** + * Shoulder for global id - used to create a common prefix on identifiers + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") Shoulder, - /* Removed for now - tried to add here but DOI Service Bean didn't like it at start-up - DoiUsername, - DoiPassword, - DoiBaseurlstring, - */ /** Optionally override http://guides.dataverse.org . */ GuidesBaseUrl, @@ -347,10 +379,16 @@ Whether Harvesting (OAI) service is enabled */ PVCustomPasswordResetAlertMessage, /* - String to describe DOI format for data files. Default is DEPENDENT. - 'DEPENDENT' means the DOI will be the Dataset DOI plus a file DOI with a slash in between. - 'INDEPENDENT' means a new global id, completely independent from the dataset-level global id. - */ + * String to describe DOI format for data files. Default is DEPENDENT. + * 'DEPENDENT' means the DOI will be the Dataset DOI plus a file DOI with a + * slash in between. 'INDEPENDENT' means a new global id, completely independent + * from the dataset-level global id. + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") DataFilePIDFormat, /* Json array of supported languages */ @@ -366,12 +404,22 @@ Whether Harvesting (OAI) service is enabled /** * Indicates if the Handle service is setup to work 'independently' (No communication with the Global Handle Registry) + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * */ + @Deprecated(forRemoval = true, since = "2024-02-13") IndependentHandleService, /** Handle to use for authentication if the default is not being used - */ + * + * @deprecated New installations should not use this database setting, but use + * the settings within {@link JvmSettings#SCOPE_PID}. + * + */ + @Deprecated(forRemoval = true, since = "2024-02-13") HandleAuthHandle, /** From b9b2715b416f5d1154d6c086cf5c556ab6bc5f3c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 13:05:07 -0500 Subject: [PATCH 081/113] Change error handling and warnings per review --- .../pidproviders/PidProviderFactoryBean.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 6f57de9ac31..d33fcf28c95 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -119,26 +119,35 @@ private void loadProviderFactories() { } private void loadProviders() { - try { - String[] providers = JvmSettings.PID_PROVIDERS.lookup(String[].class); - for (String name : providers) { - String type = JvmSettings.PID_PROVIDER_TYPE.lookup(name); - if (pidProviderFactoryMap.containsKey(type)) { - PidProvider provider = pidProviderFactoryMap.get(type).createPidProvider(name); - provider.setPidProviderServiceBean(this); - PidUtil.addToProviderList(provider); + Optional providers = JvmSettings.PID_PROVIDERS.lookupOptional(String[].class); + if (!providers.isPresent()) { + logger.warning( + "No PidProviders configured via dataverse.pid.providers. Please consider updating as older PIDProvider configuration mechanisms will be removed in a future version of Dataverse."); + return; + } else { + for (String id : providers.get()) { + Optional type = JvmSettings.PID_PROVIDER_TYPE.lookupOptional(id); + if (!type.isPresent()) { + logger.warning("PidProvider " + id + + " listed in dataverse.pid.providers is not properly configured and will not be used."); + } else { + String typeString = type.get(); + if (pidProviderFactoryMap.containsKey(typeString)) { + PidProvider provider = pidProviderFactoryMap.get(typeString).createPidProvider(id); + provider.setPidProviderServiceBean(this); + PidUtil.addToProviderList(provider); + } + } } } - } catch (NoSuchElementException e) { - logger.warning("No PidProviders configured"); - } String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol); String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority); String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder); String provider = settingsService.getValueForKey(SettingsServiceBean.Key.DoiProvider); if (protocol != null && authority != null && shoulder != null && provider != null) { - logger.warning("Found legacy settings: " + protocol + " " + authority + " " + shoulder + " " + provider); + logger.warning("Found legacy settings: " + protocol + " " + authority + " " + shoulder + " " + provider + + "Please consider updating as this PIDProvider configuration mechanism will be removed in a future version of Dataverse"); if (PidUtil.getPidProvider(protocol, authority, shoulder) == null) { PidProvider legacy = null; // Try to add a legacy provider From 92340b34e7049180fc216844b7bb05dc2176db82 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 13:05:27 -0500 Subject: [PATCH 082/113] Add testing for a valid PID generator as a config test --- .../dataverse/settings/ConfigCheckService.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/ConfigCheckService.java b/src/main/java/edu/harvard/iq/dataverse/settings/ConfigCheckService.java index a2c3f53d59d..7ca5fe04bcd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/ConfigCheckService.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/ConfigCheckService.java @@ -1,5 +1,6 @@ package edu.harvard.iq.dataverse.settings; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.util.FileUtil; import jakarta.annotation.PostConstruct; @@ -16,9 +17,10 @@ @Startup @Singleton -@DependsOn("StartupFlywayMigrator") +@DependsOn({"StartupFlywayMigrator", "PidProviderFactoryBean"}) public class ConfigCheckService { + private static final Logger logger = Logger.getLogger(ConfigCheckService.class.getCanonicalName()); public static class ConfigurationError extends RuntimeException { @@ -29,11 +31,13 @@ public ConfigurationError(String message) { @PostConstruct public void startup() { - if (!checkSystemDirectories()) { + if (!checkSystemDirectories() || !checkPidProviders()) { throw new ConfigurationError("Not all configuration checks passed successfully. See logs above."); } } + + /** * In this method, we check the existence and write-ability of all important directories we use during * normal operations. It does not include checks for the storage system. If directories are not available, @@ -78,4 +82,14 @@ public boolean checkSystemDirectories() { return success; } + /** + * Verifies that at least one PidProvider capable of editing/minting PIDs is + * configured. Requires the @DependsOn("PidProviderFactoryBean") annotation above + * since it is the @PostCOnstruct init() method of that class that loads the PidProviders + * + * @return True if all checks successful, false otherwise. + */ + private boolean checkPidProviders() { + return PidUtil.getManagedProviderIds().size() > 0; + } } From 5689474b53199dd57383774d7a16799bed5a661b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 13:23:30 -0500 Subject: [PATCH 083/113] formatting, switch if /else logic per review --- .../pidproviders/PidProviderFactoryBean.java | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index d33fcf28c95..a67bbba5f0e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -119,27 +119,27 @@ private void loadProviderFactories() { } private void loadProviders() { - Optional providers = JvmSettings.PID_PROVIDERS.lookupOptional(String[].class); - if (!providers.isPresent()) { - logger.warning( - "No PidProviders configured via dataverse.pid.providers. Please consider updating as older PIDProvider configuration mechanisms will be removed in a future version of Dataverse."); - return; - } else { - for (String id : providers.get()) { - Optional type = JvmSettings.PID_PROVIDER_TYPE.lookupOptional(id); - if (!type.isPresent()) { - logger.warning("PidProvider " + id - + " listed in dataverse.pid.providers is not properly configured and will not be used."); - } else { - String typeString = type.get(); - if (pidProviderFactoryMap.containsKey(typeString)) { - PidProvider provider = pidProviderFactoryMap.get(typeString).createPidProvider(id); - provider.setPidProviderServiceBean(this); - PidUtil.addToProviderList(provider); - } + Optional providers = JvmSettings.PID_PROVIDERS.lookupOptional(String[].class); + if (!providers.isPresent()) { + logger.warning( + "No PidProviders configured via dataverse.pid.providers. Please consider updating as older PIDProvider configuration mechanisms will be removed in a future version of Dataverse."); + return; + } else { + for (String id : providers.get()) { + Optional type = JvmSettings.PID_PROVIDER_TYPE.lookupOptional(id); + if (!type.isPresent()) { + logger.warning("PidProvider " + id + + " listed in dataverse.pid.providers is not properly configured and will not be used."); + } else { + String typeString = type.get(); + if (pidProviderFactoryMap.containsKey(typeString)) { + PidProvider provider = pidProviderFactoryMap.get(typeString).createPidProvider(id); + provider.setPidProviderServiceBean(this); + PidUtil.addToProviderList(provider); } } } + } String protocol = settingsService.getValueForKey(SettingsServiceBean.Key.Protocol); String authority = settingsService.getValueForKey(SettingsServiceBean.Key.Authority); String shoulder = settingsService.getValueForKey(SettingsServiceBean.Key.Shoulder); @@ -148,7 +148,10 @@ private void loadProviders() { if (protocol != null && authority != null && shoulder != null && provider != null) { logger.warning("Found legacy settings: " + protocol + " " + authority + " " + shoulder + " " + provider + "Please consider updating as this PIDProvider configuration mechanism will be removed in a future version of Dataverse"); - if (PidUtil.getPidProvider(protocol, authority, shoulder) == null) { + if (PidUtil.getPidProvider(protocol, authority, shoulder) != null) { + logger.warning( + "Legacy PID provider settings found - ignored since a provider for the same protocol, authority, shoulder has been registered"); + } else { PidProvider legacy = null; // Try to add a legacy provider String identifierGenerationStyle = settingsService @@ -193,22 +196,21 @@ private void loadProviders() { boolean independentHandleService = settingsService .isTrueForKey(SettingsServiceBean.Key.IndependentHandleService, false); String handleAuthHandle = settingsService.getValueForKey(SettingsServiceBean.Key.HandleAuthHandle); - + legacy = new HandlePidProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, dataFilePidFormat, "", "", index, independentHandleService, handleAuthHandle, path, passphrase); break; case "perma": String baseUrl = JvmSettings.LEGACY_PERMALINK_BASEURL.lookup(); - legacy = new PermaLinkPidProvider("legacy", "legacy", authority, shoulder, identifierGenerationStyle, - dataFilePidFormat, "", "", baseUrl, PermaLinkPidProvider.SEPARATOR); + legacy = new PermaLinkPidProvider("legacy", "legacy", authority, shoulder, + identifierGenerationStyle, dataFilePidFormat, "", "", baseUrl, + PermaLinkPidProvider.SEPARATOR); } if (legacy != null) { legacy.setPidProviderServiceBean(this); PidUtil.addToProviderList(legacy); } - } else { - logger.warning("Legacy PID provider settings found - ignored since a provider for the same protocol, authority, shoulder has been registered"); } logger.info("Have " + PidUtil.getManagedProviderIds().size() + " managed PID providers"); } @@ -230,7 +232,7 @@ String generateNewIdentifierByStoredProcedure() { public PidProvider getDefaultPidGenerator() { Optional pidProviderDefaultId = JvmSettings.PID_DEFAULT_PROVIDER.lookupOptional(String.class); - if(pidProviderDefaultId.isPresent()) { + if (pidProviderDefaultId.isPresent()) { return PidUtil.getPidProvider(pidProviderDefaultId.get()); } else { String nonNullDefaultIfKeyNotFound = ""; From 27d6354af63e3c44bb6f9f53d352fab59d62e918 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 13:47:20 -0500 Subject: [PATCH 084/113] add deprecation --- .../iq/dataverse/settings/JvmSettings.java | 74 +++++++++++++------ 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index 3240859753c..a153413a68e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -104,30 +104,7 @@ public enum JvmSettings { PID_PROVIDER_MANAGED_LIST(SCOPE_PID_PROVIDER, "managed-list"), PID_PROVIDER_EXCLUDED_LIST(SCOPE_PID_PROVIDER, "excluded-list"), - // PROVIDER DATACITE (legacy - single provider setting) - SCOPE_LEGACY_PID_DATACITE(SCOPE_PID, "datacite"), - LEGACY_DATACITE_MDS_API_URL(SCOPE_LEGACY_PID_DATACITE, "mds-api-url", "doi.baseurlstring"), - LEGACY_DATACITE_REST_API_URL(SCOPE_LEGACY_PID_DATACITE, "rest-api-url", "doi.dataciterestapiurlstring", "doi.mdcbaseurlstring"), - LEGACY_DATACITE_USERNAME(SCOPE_LEGACY_PID_DATACITE, "username", "doi.username"), - LEGACY_DATACITE_PASSWORD(SCOPE_LEGACY_PID_DATACITE, "password", "doi.password"), - - // PROVIDER EZID (legacy - single provider setting) - SCOPE_LEGACY_PID_EZID(SCOPE_PID, "ezid"), - LEGACY_EZID_API_URL(SCOPE_LEGACY_PID_EZID, "api-url"), - LEGACY_EZID_USERNAME(SCOPE_LEGACY_PID_EZID, "username"), - LEGACY_EZID_PASSWORD(SCOPE_LEGACY_PID_EZID, "password"), - - // PROVIDER PERMALINK (legacy - single provider setting) - SCOPE_LEGACY_PID_PERMALINK(SCOPE_PID, "permalink"), - LEGACY_PERMALINK_BASEURL(SCOPE_LEGACY_PID_PERMALINK, "base-url", "perma.baseurlstring"), - - // PROVIDER HANDLE (legacy - single provider setting) - SCOPE_LEGACY_PID_HANDLENET(SCOPE_PID, "handlenet"), - LEGACY_HANDLENET_INDEX(SCOPE_LEGACY_PID_HANDLENET, "index", "dataverse.handlenet.index"), - SCOPE_LEGACY_PID_HANDLENET_KEY(SCOPE_LEGACY_PID_HANDLENET, "key"), - LEGACY_HANDLENET_KEY_PATH(SCOPE_LEGACY_PID_HANDLENET_KEY, "path", "dataverse.handlenet.admcredfile"), - LEGACY_HANDLENET_KEY_PASSPHRASE(SCOPE_LEGACY_PID_HANDLENET_KEY, "passphrase", "dataverse.handlenet.admprivphrase"), - + // PROVIDER EZID - these settings were formerly kept together with DataCite ones SCOPE_PID_EZID(SCOPE_PID_PROVIDER, "ezid"), EZID_API_URL(SCOPE_PID_EZID, "api-url"), @@ -155,6 +132,55 @@ public enum JvmSettings { HANDLENET_KEY_PATH(SCOPE_PID_HANDLENET_KEY, "path"), HANDLENET_KEY_PASSPHRASE(SCOPE_PID_HANDLENET_KEY, "passphrase"), + /* + * The deprecated legacy settings below are from when you could only have a + * single PIDProvider. They mirror the settings above, but are global,not within + * the SCOPE_PID_PROVIDER of an individual provider. + */ + /** + * DEPRECATED PROVIDER DATACITE + * + * @deprecated - legacy single provider setting providing backward compatibility + */ + @Deprecated(forRemoval = true, since = "2024-02-13") + SCOPE_LEGACY_PID_DATACITE(SCOPE_PID, "datacite"), + LEGACY_DATACITE_MDS_API_URL(SCOPE_LEGACY_PID_DATACITE, "mds-api-url", "doi.baseurlstring"), + LEGACY_DATACITE_REST_API_URL(SCOPE_LEGACY_PID_DATACITE, "rest-api-url", "doi.dataciterestapiurlstring", + "doi.mdcbaseurlstring"), + LEGACY_DATACITE_USERNAME(SCOPE_LEGACY_PID_DATACITE, "username", "doi.username"), + LEGACY_DATACITE_PASSWORD(SCOPE_LEGACY_PID_DATACITE, "password", "doi.password"), + + /** + * DEPRECATED PROVIDER EZID + * + * @deprecated - legacy single provider setting providing backward compatibility + */ + @Deprecated(forRemoval = true, since = "2024-02-13") + SCOPE_LEGACY_PID_EZID(SCOPE_PID, "ezid"), LEGACY_EZID_API_URL(SCOPE_LEGACY_PID_EZID, "api-url"), + LEGACY_EZID_USERNAME(SCOPE_LEGACY_PID_EZID, "username"), LEGACY_EZID_PASSWORD(SCOPE_LEGACY_PID_EZID, "password"), + + /** + * DEPRECATED PROVIDER PERMALINK + * + * @deprecated - legacy single provider setting providing backward compatibility + */ + @Deprecated(forRemoval = true, since = "2024-02-13") + SCOPE_LEGACY_PID_PERMALINK(SCOPE_PID, "permalink"), + LEGACY_PERMALINK_BASEURL(SCOPE_LEGACY_PID_PERMALINK, "base-url", "perma.baseurlstring"), + + /** + * DEPRECATED PROVIDER HANDLE + * + * @deprecated - legacy single provider setting providing backward compatibility + */ + @Deprecated(forRemoval = true, since = "2024-02-13") + SCOPE_LEGACY_PID_HANDLENET(SCOPE_PID, "handlenet"), + LEGACY_HANDLENET_INDEX(SCOPE_LEGACY_PID_HANDLENET, "index", "dataverse.handlenet.index"), + @Deprecated(forRemoval = true, since = "2024-02-13") + SCOPE_LEGACY_PID_HANDLENET_KEY(SCOPE_LEGACY_PID_HANDLENET, "key"), + LEGACY_HANDLENET_KEY_PATH(SCOPE_LEGACY_PID_HANDLENET_KEY, "path", "dataverse.handlenet.admcredfile"), + LEGACY_HANDLENET_KEY_PASSPHRASE(SCOPE_LEGACY_PID_HANDLENET_KEY, "passphrase", "dataverse.handlenet.admprivphrase"), + // SPI SETTINGS SCOPE_SPI(PREFIX, "spi"), SCOPE_EXPORTERS(SCOPE_SPI, "exporters"), From 82afe7efff3d3fd75a2bb75f09ebb1e85722e58d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 13:50:40 -0500 Subject: [PATCH 085/113] move pid provider's dir setting to spi scope --- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 2 +- .../java/edu/harvard/iq/dataverse/settings/JvmSettings.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index a67bbba5f0e..94ff7de2b27 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -73,7 +73,7 @@ private void loadProviderFactories() { * Step 1 - find the PROVIDERS dir and add all jar files there to a class loader */ List jarUrls = new ArrayList<>(); - Optional providerPathSetting = JvmSettings.PROVIDERS_DIRECTORY.lookupOptional(String.class); + Optional providerPathSetting = JvmSettings.PIDPROVIDERS_DIRECTORY.lookupOptional(String.class); if (providerPathSetting.isPresent()) { Path providersDir = Paths.get(providerPathSetting.get()); // Get all JAR files from the configured directory diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index a153413a68e..b92618dab89 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -93,7 +93,6 @@ public enum JvmSettings { SCOPE_PID(PREFIX, "pid"), PID_PROVIDERS(SCOPE_PID, "providers"), PID_DEFAULT_PROVIDER(SCOPE_PID, "default-provider"), - PROVIDERS_DIRECTORY(SCOPE_PID, "provider-implementations-directory"), SCOPE_PID_PROVIDER(SCOPE_PID), PID_PROVIDER_TYPE(SCOPE_PID_PROVIDER, "type"), PID_PROVIDER_LABEL(SCOPE_PID_PROVIDER, "label"), @@ -185,6 +184,8 @@ public enum JvmSettings { SCOPE_SPI(PREFIX, "spi"), SCOPE_EXPORTERS(SCOPE_SPI, "exporters"), EXPORTERS_DIRECTORY(SCOPE_EXPORTERS, "directory"), + SCOPE_PIDPROVIDERS(SCOPE_SPI, "pidproviders"), + PIDPROVIDERS_DIRECTORY(SCOPE_PIDPROVIDERS, "directory"), // MAIL SETTINGS SCOPE_MAIL(PREFIX, "mail"), From 866a01653ec2b147db347e3d683457a95301520c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 14:28:42 -0500 Subject: [PATCH 086/113] change flyway name, tweak release note, delete unused test class --- doc/release-notes/3623-multipid.md | 6 +-- ...V6.1.0.4__3623-multiple-pid-providers.sql} | 0 .../pidproviders/PidProviderTest.java | 52 ------------------- 3 files changed, 3 insertions(+), 55 deletions(-) rename src/main/resources/db/migration/{V6.0.0.20__3623-multiple-pid-providers.sql => V6.1.0.4__3623-multiple-pid-providers.sql} (100%) delete mode 100644 src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java diff --git a/doc/release-notes/3623-multipid.md b/doc/release-notes/3623-multipid.md index abeb96dd477..8c13eb1aec6 100644 --- a/doc/release-notes/3623-multipid.md +++ b/doc/release-notes/3623-multipid.md @@ -5,13 +5,13 @@ the combination where the account can mint new PIDs). It also adds the ability f DataCite, EZId, Handle, and PermaLink providers to be dynamically added as separate jar files. These changes require per-provider settings rather than the global PID settings previously supported. While backward compatibility -for installations using a single PID Provider account is provided, updating to use the new microprofile settings is highly recommended. +for installations using a single PID Provider account is provided, updating to use the new microprofile settings is highly recommended +and will be required in a future version. New microprofile settings (where * indicates a provider id indicating which provider the setting is for): dataverse.pid.providers dataverse.pid.default-provider -dataverse.pid.provider-implementations-directory dataverse.pid.*.type dataverse.pid.*.label dataverse.pid.*.authority @@ -34,4 +34,4 @@ dataverse.pid.*.handlenet.independent-service dataverse.pid.*.handlenet.auth-handle dataverse.pid.*.handlenet.key.path dataverse.pid.*.handlenet.key.passphrase - +dataverse.spi.pidproviders.directory diff --git a/src/main/resources/db/migration/V6.0.0.20__3623-multiple-pid-providers.sql b/src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql similarity index 100% rename from src/main/resources/db/migration/V6.0.0.20__3623-multiple-pid-providers.sql rename to src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java deleted file mode 100644 index 593396dd467..00000000000 --- a/src/test/java/edu/harvard/iq/dataverse/pidproviders/PidProviderTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package edu.harvard.iq.dataverse.pidproviders; - -import edu.harvard.iq.dataverse.engine.TestCommandContext; -import edu.harvard.iq.dataverse.engine.command.CommandContext; -import edu.harvard.iq.dataverse.pidproviders.PidProvider; -import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; -import edu.harvard.iq.dataverse.settings.SettingsServiceBean; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.junit.jupiter.MockitoExtension; - - -import static org.junit.jupiter.api.Assertions.*; - -/** - * - * @author michael - */ -@ExtendWith(MockitoExtension.class) -public class PidProviderTest { - - @Mock - private SettingsServiceBean settingsServiceBean; - - @InjectMocks - PidProviderFactoryBean pidProviderFactoryBean = new PidProviderFactoryBean(); - - CommandContext ctxt; - - @BeforeEach - public void setup() { - MockitoAnnotations.initMocks(this); - ctxt = new TestCommandContext(){ - @Override - public PidProviderFactoryBean pidProviderFactory() { - return pidProviderFactoryBean; - } - }; - } - - -} From 7106ef68e7ba203b2de8f06b7fbc0777d9138318 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 13 Feb 2024 16:32:44 -0500 Subject: [PATCH 087/113] temporary flyway change --- ...id-providers.sql => V6.1.0.3__3623-multiple-pid-providers.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V6.1.0.4__3623-multiple-pid-providers.sql => V6.1.0.3__3623-multiple-pid-providers.sql} (100%) diff --git a/src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql b/src/main/resources/db/migration/V6.1.0.3__3623-multiple-pid-providers.sql similarity index 100% rename from src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql rename to src/main/resources/db/migration/V6.1.0.3__3623-multiple-pid-providers.sql From 47885b3e7e7ae641097c0e0c1b97a1fbfb74ed2a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 14 Feb 2024 12:43:25 -0500 Subject: [PATCH 088/113] use new settings in install --- scripts/api/setup-all.sh | 4 ---- scripts/installer/as-setup.sh | 12 +++++++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/api/setup-all.sh b/scripts/api/setup-all.sh index e247caa72b5..5ddd9a35fdc 100755 --- a/scripts/api/setup-all.sh +++ b/scripts/api/setup-all.sh @@ -57,10 +57,6 @@ echo "- Allow internal signup" curl -X PUT -d yes "${DATAVERSE_URL}/api/admin/settings/:AllowSignUp" curl -X PUT -d "/dataverseuser.xhtml?editMode=CREATE" "${DATAVERSE_URL}/api/admin/settings/:SignUpUrl" -curl -X PUT -d doi "${DATAVERSE_URL}/api/admin/settings/:Protocol" -curl -X PUT -d 10.5072 "${DATAVERSE_URL}/api/admin/settings/:Authority" -curl -X PUT -d "FK2/" "${DATAVERSE_URL}/api/admin/settings/:Shoulder" -curl -X PUT -d DataCite "${DATAVERSE_URL}/api/admin/settings/:DoiProvider" curl -X PUT -d burrito "${DATAVERSE_URL}/api/admin/settings/BuiltinUsers.KEY" curl -X PUT -d localhost-only "${DATAVERSE_URL}/api/admin/settings/:BlockedApiPolicy" curl -X PUT -d 'native/http' "${DATAVERSE_URL}/api/admin/settings/:UploadMethods" diff --git a/scripts/installer/as-setup.sh b/scripts/installer/as-setup.sh index fc5b378cff5..9e7f5b84f26 100755 --- a/scripts/installer/as-setup.sh +++ b/scripts/installer/as-setup.sh @@ -106,9 +106,15 @@ function preliminary_setup() # (we can no longer offer EZID with their shared test account) # jvm-options use colons as separators, escape as literal DOI_BASEURL_ESC=`echo $DOI_BASEURL | sed -e 's/:/\\\:/'` - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.datacite.username=${DOI_USERNAME}" - ./asadmin $ASADMIN_OPTS create-jvm-options '\-Ddataverse.pid.datacite.password=${ALIAS=doi_password_alias}' - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.datacite.mds-api-url=$DOI_BASEURL_ESC" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.providers=testDC" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.type=datacite" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.label=TestDataCite" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.authority=10.5072" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.shoulder=FK2/" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.username=${DOI_USERNAME}" + ./asadmin $ASADMIN_OPTS create-jvm-options '\-Ddataverse.pid.testDC.datacite.password=${ALIAS=doi_password_alias}' + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.mds-api-url=$DOI_BASEURL_ESC" + # jvm-options use colons as separators, escape as literal DOI_DATACITERESTAPIURL_ESC=`echo $DOI_DATACITERESTAPIURL | sed -e 's/:/\\\:/'` From d3d39c366bca52db72c2d6553807de7fccfbc6f6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 14 Feb 2024 13:28:41 -0500 Subject: [PATCH 089/113] Revert "temporary flyway change" This reverts commit 7106ef68e7ba203b2de8f06b7fbc0777d9138318. --- ...id-providers.sql => V6.1.0.4__3623-multiple-pid-providers.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V6.1.0.3__3623-multiple-pid-providers.sql => V6.1.0.4__3623-multiple-pid-providers.sql} (100%) diff --git a/src/main/resources/db/migration/V6.1.0.3__3623-multiple-pid-providers.sql b/src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql similarity index 100% rename from src/main/resources/db/migration/V6.1.0.3__3623-multiple-pid-providers.sql rename to src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql From d7a878d89415259f634f79512ff807745e5d7c90 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 14 Feb 2024 15:32:37 -0500 Subject: [PATCH 090/113] fix rest api setting --- scripts/installer/as-setup.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/installer/as-setup.sh b/scripts/installer/as-setup.sh index 9e7f5b84f26..53550800dd6 100755 --- a/scripts/installer/as-setup.sh +++ b/scripts/installer/as-setup.sh @@ -114,11 +114,9 @@ function preliminary_setup() ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.username=${DOI_USERNAME}" ./asadmin $ASADMIN_OPTS create-jvm-options '\-Ddataverse.pid.testDC.datacite.password=${ALIAS=doi_password_alias}' ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.mds-api-url=$DOI_BASEURL_ESC" - - # jvm-options use colons as separators, escape as literal DOI_DATACITERESTAPIURL_ESC=`echo $DOI_DATACITERESTAPIURL | sed -e 's/:/\\\:/'` - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.datacite.rest-api-url=$DOI_DATACITERESTAPIURL_ESC" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.rest-api-url=$DOI_DATACITERESTAPIURL_ESC" ./asadmin $ASADMIN_OPTS create-jvm-options "-Ddataverse.timerServer=true" From 4200f9f14e84225d67e52f06e25fc26e30877c03 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 14 Feb 2024 15:32:54 -0500 Subject: [PATCH 091/113] handle spaces in the pidproviders setting --- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 94ff7de2b27..89f8fc5f04e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -126,6 +126,8 @@ private void loadProviders() { return; } else { for (String id : providers.get()) { + //Allows spaces in PID_PROVIDERS setting + id=id.trim(); Optional type = JvmSettings.PID_PROVIDER_TYPE.lookupOptional(id); if (!type.isPresent()) { logger.warning("PidProvider " + id From 2787b881bc9c96a880a9794763edf6a437e0ba89 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 14 Feb 2024 15:33:12 -0500 Subject: [PATCH 092/113] add note in Harvard setup --- scripts/api/setup-optional-harvard.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/api/setup-optional-harvard.sh b/scripts/api/setup-optional-harvard.sh index fcbcc08a8e6..1311464e8ff 100755 --- a/scripts/api/setup-optional-harvard.sh +++ b/scripts/api/setup-optional-harvard.sh @@ -3,6 +3,7 @@ SERVER=http://localhost:8080/api echo "Setting up Harvard-specific settings" # :Authority and :Shoulder are commented out so this script can be used on test servers +# Should now use the new multipid JVM options instead of these settings #curl -X PUT -d 10.7910 "$SERVER/admin/settings/:Authority" #curl -X PUT -d "DVN/" "$SERVER/admin/settings/:Shoulder" echo "- Application Status header" From 37249eb4adc9c64fcc66dbee9e1612a811fc6a6f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 16 Feb 2024 14:07:09 -0500 Subject: [PATCH 093/113] refactoring/cleaning DataCite provider, drop cache --- .../edu/harvard/iq/dataverse/Dataset.java | 1 + .../pidproviders/AbstractPidProvider.java | 289 +--------- .../pidproviders/XmlMetadataTemplate.java | 313 +++++++++++ .../datacite/DOIDataCiteRegisterCache.java | 90 ---- .../datacite/DOIDataCiteRegisterService.java | 492 +----------------- .../doi/datacite/DataCiteDOIProvider.java | 183 ++++--- .../doi/datacite/DataCiteRESTfullClient.java | 21 +- 7 files changed, 456 insertions(+), 933 deletions(-) create mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java delete mode 100644 src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataset.java b/src/main/java/edu/harvard/iq/dataverse/Dataset.java index a2f560bc959..bafec4ed7ba 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataset.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataset.java @@ -317,6 +317,7 @@ public boolean isDeaccessioned() { } return hasDeaccessionedVersions; // since any published version would have already returned } + public DatasetVersion getLatestVersion() { return getVersions().get(0); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index 9b98c57e807..dfee7ce21dd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -2,7 +2,6 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.DatasetAuthor; import edu.harvard.iq.dataverse.DatasetField; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; @@ -11,18 +10,11 @@ import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.lang3.RandomStringUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; - import com.beust.jcommander.Strings; public abstract class AbstractPidProvider implements PidProvider { @@ -464,285 +456,6 @@ private String generateIdentifierFromStoredProcedureDependent(DataFile datafile, return identifier; } - public class GlobalIdMetadataTemplate { - - private String template; - - public GlobalIdMetadataTemplate() { - try (InputStream in = GlobalIdMetadataTemplate.class - .getResourceAsStream("datacite_metadata_template.xml")) { - template = new String(in.readAllBytes(), StandardCharsets.UTF_8); - } catch (Exception e) { - logger.log(Level.SEVERE, "datacite metadata template load error"); - logger.log(Level.SEVERE, "String " + e.toString()); - logger.log(Level.SEVERE, "localized message " + e.getLocalizedMessage()); - logger.log(Level.SEVERE, "cause " + e.getCause()); - logger.log(Level.SEVERE, "message " + e.getMessage()); - } - } - - private String xmlMetadata; - private String identifier; - private List datafileIdentifiers; - private List creators; - private String title; - private String publisher; - private String publisherYear; - private List authors; - private String description; - private List contacts; - private List producers; - - public List getProducers() { - return producers; - } - - public void setProducers(List producers) { - this.producers = producers; - } - - public List getContacts() { - return contacts; - } - - public void setContacts(List contacts) { - this.contacts = contacts; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public List getDatafileIdentifiers() { - return datafileIdentifiers; - } - - public void setDatafileIdentifiers(List datafileIdentifiers) { - this.datafileIdentifiers = datafileIdentifiers; - } - - public GlobalIdMetadataTemplate(String xmlMetaData) { - this.xmlMetadata = xmlMetaData; - Document doc = Jsoup.parseBodyFragment(xmlMetaData); - Elements identifierElements = doc.select("identifier"); - if (identifierElements.size() > 0) { - identifier = identifierElements.get(0).html(); - } - Elements creatorElements = doc.select("creatorName"); - creators = new ArrayList<>(); - for (Element creatorElement : creatorElements) { - creators.add(creatorElement.html()); - } - Elements titleElements = doc.select("title"); - if (titleElements.size() > 0) { - title = titleElements.get(0).html(); - } - Elements publisherElements = doc.select("publisher"); - if (publisherElements.size() > 0) { - publisher = publisherElements.get(0).html(); - } - Elements publisherYearElements = doc.select("publicationYear"); - if (publisherYearElements.size() > 0) { - publisherYear = publisherYearElements.get(0).html(); - } - } - - public String generateXML(DvObject dvObject) { - // Can't use "UNKNOWN" here because DataCite will respond with "[facet - // 'pattern'] the value 'unknown' is not accepted by the pattern '[\d]{4}'" - String publisherYearFinal = "9999"; - // FIXME: Investigate why this.publisherYear is sometimes null now that pull - // request #4606 has been merged. - if (this.publisherYear != null) { - // Added to prevent a NullPointerException when trying to destroy datasets when - // using DataCite rather than EZID. - publisherYearFinal = this.publisherYear; - } - xmlMetadata = template.replace("${identifier}", getIdentifier().trim()).replace("${title}", this.title) - .replace("${publisher}", this.publisher).replace("${publisherYear}", publisherYearFinal) - .replace("${description}", this.description); - StringBuilder creatorsElement = new StringBuilder(); - for (DatasetAuthor author : authors) { - creatorsElement.append(""); - creatorsElement.append(author.getName().getDisplayValue()); - creatorsElement.append(""); - - if (author.getIdType() != null && author.getIdValue() != null && !author.getIdType().isEmpty() - && !author.getIdValue().isEmpty() && author.getAffiliation() != null - && !author.getAffiliation().getDisplayValue().isEmpty()) { - - if (author.getIdType().equals("ORCID")) { - creatorsElement.append( - "" - + author.getIdValue() + ""); - } - if (author.getIdType().equals("ISNI")) { - creatorsElement.append( - "" - + author.getIdValue() + ""); - } - if (author.getIdType().equals("LCNA")) { - creatorsElement.append( - "" - + author.getIdValue() + ""); - } - } - if (author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { - creatorsElement - .append("" + author.getAffiliation().getDisplayValue() + ""); - } - creatorsElement.append(""); - } - xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); - - StringBuilder contributorsElement = new StringBuilder(); - for (String[] contact : this.getContacts()) { - if (!contact[0].isEmpty()) { - contributorsElement.append("" - + contact[0] + ""); - if (!contact[1].isEmpty()) { - contributorsElement.append("" + contact[1] + ""); - } - contributorsElement.append(""); - } - } - for (String[] producer : this.getProducers()) { - contributorsElement.append("" + producer[0] - + ""); - if (!producer[1].isEmpty()) { - contributorsElement.append("" + producer[1] + ""); - } - contributorsElement.append(""); - } - - String relIdentifiers = generateRelatedIdentifiers(dvObject); - - xmlMetadata = xmlMetadata.replace("${relatedIdentifiers}", relIdentifiers); - - xmlMetadata = xmlMetadata.replace("{$contributors}", contributorsElement.toString()); - return xmlMetadata; - } - - private String generateRelatedIdentifiers(DvObject dvObject) { - - StringBuilder sb = new StringBuilder(); - if (dvObject.isInstanceofDataset()) { - Dataset dataset = (Dataset) dvObject; - if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { - - datafileIdentifiers = new ArrayList<>(); - for (DataFile dataFile : dataset.getFiles()) { - if (!dataFile.getGlobalId().asString().isEmpty()) { - if (sb.toString().isEmpty()) { - sb.append(""); - } - sb.append("" - + dataFile.getGlobalId() + ""); - } - } - - if (!sb.toString().isEmpty()) { - sb.append(""); - } - } - } else if (dvObject.isInstanceofDataFile()) { - DataFile df = (DataFile) dvObject; - sb.append(""); - sb.append("" - + df.getOwner().getGlobalId() + ""); - sb.append(""); - } - return sb.toString(); - } - - public void generateFileIdentifiers(DvObject dvObject) { - - if (dvObject.isInstanceofDataset()) { - Dataset dataset = (Dataset) dvObject; - - if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { - - datafileIdentifiers = new ArrayList<>(); - for (DataFile dataFile : dataset.getFiles()) { - datafileIdentifiers.add(dataFile.getIdentifier()); - int x = xmlMetadata.indexOf("") - 1; - xmlMetadata = xmlMetadata.replace("{relatedIdentifier}", dataFile.getIdentifier()); - xmlMetadata = xmlMetadata.substring(0, x) - + "${relatedIdentifier}" - + template.substring(x, template.length() - 1); - - } - - } else { - xmlMetadata = xmlMetadata.replace( - "${relatedIdentifier}", - ""); - } - } - } - - public String getTemplate() { - return template; - } - - public void setTemplate(String templateIn) { - template = templateIn; - } - - public String getIdentifier() { - return identifier; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } - - public List getCreators() { - return creators; - } - - public void setCreators(List creators) { - this.creators = creators; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getPublisher() { - return publisher; - } - - public void setPublisher(String publisher) { - this.publisher = publisher; - } - - public String getPublisherYear() { - return publisherYear; - } - - public void setPublisherYear(String publisherYear) { - this.publisherYear = publisherYear; - } - } - public String getMetadataFromDvObject(String identifier, Map metadata, DvObject dvObject) { Dataset dataset = null; @@ -753,7 +466,7 @@ public String getMetadataFromDvObject(String identifier, Map met dataset = (Dataset) dvObject.getOwner(); } - GlobalIdMetadataTemplate metadataTemplate = new GlobalIdMetadataTemplate(); + XmlMetadataTemplate metadataTemplate = new XmlMetadataTemplate(); metadataTemplate.setIdentifier(identifier.substring(identifier.indexOf(':') + 1)); metadataTemplate.setCreators(Arrays.asList(metadata.get("datacite.creator").split("; "))); metadataTemplate.setAuthors(dataset.getLatestVersion().getDatasetAuthors()); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java new file mode 100644 index 00000000000..d91c382995f --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java @@ -0,0 +1,313 @@ +package edu.harvard.iq.dataverse.pidproviders; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetAuthor; +import edu.harvard.iq.dataverse.DvObject; + +public class XmlMetadataTemplate { + + private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.DataCiteMetadataTemplate"); + private static String template; + + static { + try (InputStream in = XmlMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { + template = new String(in.readAllBytes(), StandardCharsets.UTF_8); + } catch (Exception e) { + logger.log(Level.SEVERE, "datacite metadata template load error"); + logger.log(Level.SEVERE, "String " + e.toString()); + logger.log(Level.SEVERE, "localized message " + e.getLocalizedMessage()); + logger.log(Level.SEVERE, "cause " + e.getCause()); + logger.log(Level.SEVERE, "message " + e.getMessage()); + } + } + + private String xmlMetadata; + private String identifier; + private List datafileIdentifiers; + private List creators; + private String title; + private String publisher; + private String publisherYear; + private List authors; + private String description; + private List contacts; + private List producers; + + public List getProducers() { + return producers; + } + + public void setProducers(List producers) { + this.producers = producers; + } + + public List getContacts() { + return contacts; + } + + public void setContacts(List contacts) { + this.contacts = contacts; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(List authors) { + this.authors = authors; + } + + public XmlMetadataTemplate() { + } + + public List getDatafileIdentifiers() { + return datafileIdentifiers; + } + + public void setDatafileIdentifiers(List datafileIdentifiers) { + this.datafileIdentifiers = datafileIdentifiers; + } + + public XmlMetadataTemplate(String xmlMetaData) { + this.xmlMetadata = xmlMetaData; + Document doc = Jsoup.parseBodyFragment(xmlMetaData); + Elements identifierElements = doc.select("identifier"); + if (identifierElements.size() > 0) { + identifier = identifierElements.get(0).html(); + } + Elements creatorElements = doc.select("creatorName"); + creators = new ArrayList<>(); + for (Element creatorElement : creatorElements) { + creators.add(creatorElement.html()); + } + Elements titleElements = doc.select("title"); + if (titleElements.size() > 0) { + title = titleElements.get(0).html(); + } + Elements publisherElements = doc.select("publisher"); + if (publisherElements.size() > 0) { + publisher = publisherElements.get(0).html(); + } + Elements publisherYearElements = doc.select("publicationYear"); + if (publisherYearElements.size() > 0) { + publisherYear = publisherYearElements.get(0).html(); + } + } + + public String generateXML(DvObject dvObject) { + // Can't use "UNKNOWN" here because DataCite will respond with "[facet + // 'pattern'] the value 'unknown' is not accepted by the pattern '[\d]{4}'" + String publisherYearFinal = "9999"; + // FIXME: Investigate why this.publisherYear is sometimes null now that pull + // request #4606 has been merged. + if (this.publisherYear != null) { + // Added to prevent a NullPointerException when trying to destroy datasets when + // using DataCite rather than EZID. + publisherYearFinal = this.publisherYear; + } + xmlMetadata = template.replace("${identifier}", getIdentifier().trim()).replace("${title}", this.title) + .replace("${publisher}", this.publisher).replace("${publisherYear}", publisherYearFinal) + .replace("${description}", this.description); + + StringBuilder creatorsElement = new StringBuilder(); + if (authors != null && !authors.isEmpty()) { + for (DatasetAuthor author : authors) { + creatorsElement.append(""); + creatorsElement.append(author.getName().getDisplayValue()); + creatorsElement.append(""); + + if (author.getIdType() != null && author.getIdValue() != null && !author.getIdType().isEmpty() + && !author.getIdValue().isEmpty() && author.getAffiliation() != null + && !author.getAffiliation().getDisplayValue().isEmpty()) { + + if (author.getIdType().equals("ORCID")) { + creatorsElement.append( + "" + + author.getIdValue() + ""); + } + if (author.getIdType().equals("ISNI")) { + creatorsElement.append( + "" + + author.getIdValue() + ""); + } + if (author.getIdType().equals("LCNA")) { + creatorsElement.append( + "" + + author.getIdValue() + ""); + } + } + if (author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { + creatorsElement + .append("" + author.getAffiliation().getDisplayValue() + ""); + } + creatorsElement.append(""); + } + + } else { + creatorsElement.append("").append(AbstractPidProvider.UNAVAILABLE) + .append(""); + } + + xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); + + StringBuilder contributorsElement = new StringBuilder(); + if (this.getContacts() != null) { + for (String[] contact : this.getContacts()) { + if (!contact[0].isEmpty()) { + contributorsElement.append("" + + contact[0] + ""); + if (!contact[1].isEmpty()) { + contributorsElement.append("" + contact[1] + ""); + } + contributorsElement.append(""); + } + } + } + + if (this.getProducers() != null) { + for (String[] producer : this.getProducers()) { + contributorsElement.append("" + producer[0] + + ""); + if (!producer[1].isEmpty()) { + contributorsElement.append("" + producer[1] + ""); + } + contributorsElement.append(""); + } + } + + String relIdentifiers = generateRelatedIdentifiers(dvObject); + + xmlMetadata = xmlMetadata.replace("${relatedIdentifiers}", relIdentifiers); + + xmlMetadata = xmlMetadata.replace("{$contributors}", contributorsElement.toString()); + return xmlMetadata; + } + + private String generateRelatedIdentifiers(DvObject dvObject) { + + StringBuilder sb = new StringBuilder(); + if (dvObject.isInstanceofDataset()) { + Dataset dataset = (Dataset) dvObject; + if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { + + datafileIdentifiers = new ArrayList<>(); + for (DataFile dataFile : dataset.getFiles()) { + if (dataFile.getGlobalId() != null) { + if (sb.toString().isEmpty()) { + sb.append(""); + } + sb.append("" + + dataFile.getGlobalId() + ""); + } + } + + if (!sb.toString().isEmpty()) { + sb.append(""); + } + } + } else if (dvObject.isInstanceofDataFile()) { + DataFile df = (DataFile) dvObject; + sb.append(""); + sb.append("" + + df.getOwner().getGlobalId() + ""); + sb.append(""); + } + return sb.toString(); + } + + public void generateFileIdentifiers(DvObject dvObject) { + + if (dvObject.isInstanceofDataset()) { + Dataset dataset = (Dataset) dvObject; + + if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { + + datafileIdentifiers = new ArrayList<>(); + for (DataFile dataFile : dataset.getFiles()) { + datafileIdentifiers.add(dataFile.getIdentifier()); + int x = xmlMetadata.indexOf("") - 1; + xmlMetadata = xmlMetadata.replace("{relatedIdentifier}", dataFile.getIdentifier()); + xmlMetadata = xmlMetadata.substring(0, x) + "${relatedIdentifier}" + + template.substring(x, template.length() - 1); + + } + + } else { + xmlMetadata = xmlMetadata.replace( + "${relatedIdentifier}", + ""); + } + } + } + + public static String getTemplate() { + return template; + } + + public static void setTemplate(String template) { + XmlMetadataTemplate.template = template; + } + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public List getCreators() { + return creators; + } + + public void setCreators(List creators) { + this.creators = creators; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getPublisher() { + return publisher; + } + + public void setPublisher(String publisher) { + this.publisher = publisher; + } + + public String getPublisherYear() { + return publisherYear; + } + + public void setPublisherYear(String publisherYear) { + this.publisherYear = publisherYear; + } + +} \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java deleted file mode 100644 index 4d296282c91..00000000000 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterCache.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package edu.harvard.iq.dataverse.pidproviders.doi.datacite; - - -import java.io.Serializable; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Lob; -import jakarta.persistence.NamedQueries; -import jakarta.persistence.NamedQuery; -import org.hibernate.validator.constraints.NotBlank; - -/** - * - * @author luopc - */ -@NamedQueries( - @NamedQuery( name="DOIDataCiteRegisterCache.findByDoi", - query="SELECT d FROM DOIDataCiteRegisterCache d WHERE d.doi=:doi") -) -@Entity -public class DOIDataCiteRegisterCache implements Serializable{ - - private static final long serialVersionUID = 8030143094734315681L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotBlank - @Column(unique=true) - private String doi; - - @NotBlank - private String url; - - @NotBlank - private String status; - - @NotBlank - @Lob - private String xml; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getDoi() { - return doi; - } - - public void setDoi(String doi) { - this.doi = doi; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getXml() { - return xml; - } - - public void setXml(String xml) { - this.xml = xml; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } -} \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java index 7ac8d6e48e3..d67ce72976f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java @@ -6,103 +6,37 @@ package edu.harvard.iq.dataverse.pidproviders.doi.datacite; import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.text.StringEscapeUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.DatasetAuthor; import edu.harvard.iq.dataverse.DatasetField; -import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; -import edu.harvard.iq.dataverse.settings.JvmSettings; -import jakarta.ejb.EJB; -import jakarta.ejb.Stateless; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.persistence.TypedQuery; +import edu.harvard.iq.dataverse.pidproviders.XmlMetadataTemplate; /** * * @author luopc */ -@Stateless public class DOIDataCiteRegisterService { private static final Logger logger = Logger.getLogger(DOIDataCiteRegisterService.class.getCanonicalName()); - - @PersistenceContext(unitName = "VDCNet-ejbPU") - private EntityManager em; - - @EJB - DataverseServiceBean dataverseService; - - @EJB - DataCiteDOIProvider doiDataCiteServiceBean; //A singleton since it, and the httpClient in it can be reused. private DataCiteRESTfullClient client=null; - - private DataCiteRESTfullClient getClient() throws IOException { - if (client == null) { - client = new DataCiteRESTfullClient( - JvmSettings.DATACITE_MDS_API_URL.lookup(), - JvmSettings.DATACITE_USERNAME.lookup(), - JvmSettings.DATACITE_PASSWORD.lookup() - ); - } - return client; - } - - /** - * This method is deprecated and unused. We switched away from this method - * when adjusting the code to reserve DOIs from DataCite on dataset create. - * - * Note that the DOIDataCiteRegisterCache entity/table used in this method - * might be a candidate for deprecation as well. Removing it would require - * some refactoring as it is used throughout the DataCite code. - */ - @Deprecated - public String createIdentifierLocal(String identifier, Map metadata, DvObject dvObject) { - String xmlMetadata = getMetadataFromDvObject(identifier, metadata, dvObject); - String status = metadata.get("_status").trim(); - String target = metadata.get("_target"); - String retString = ""; - DOIDataCiteRegisterCache rc = findByDOI(identifier); - if (rc == null) { - rc = new DOIDataCiteRegisterCache(); - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("reserved"); - rc.setUrl(target); - em.persist(rc); - } else { - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("reserved"); - rc.setUrl(target); - } - retString = "success to reserved " + identifier; - - return retString; + public DOIDataCiteRegisterService(String url, String username, String password) { + client = new DataCiteRESTfullClient(url, username, password); } /** @@ -119,43 +53,17 @@ public String createIdentifierLocal(String identifier, Map metad public String reserveIdentifier(String identifier, Map metadata, DvObject dvObject) throws IOException { String retString = ""; String xmlMetadata = getMetadataFromDvObject(identifier, metadata, dvObject); - DOIDataCiteRegisterCache rc = findByDOI(identifier); - String target = metadata.get("_target"); - if (rc != null) { - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - // DataCite uses the term "draft" instead of "reserved". - rc.setStatus("reserved"); - if (target == null || target.trim().length() == 0) { - target = rc.getUrl(); - } else { - rc.setUrl(target); - } - } - DataCiteRESTfullClient client = getClient(); retString = client.postMetadata(xmlMetadata); - + return retString; } public String registerIdentifier(String identifier, Map metadata, DvObject dvObject) throws IOException { String retString = ""; String xmlMetadata = getMetadataFromDvObject(identifier, metadata, dvObject); - DOIDataCiteRegisterCache rc = findByDOI(identifier); String target = metadata.get("_target"); - if (rc != null) { - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("public"); - if (target == null || target.trim().length() == 0) { - target = rc.getUrl(); - } else { - rc.setUrl(target); - } - } - DataCiteRESTfullClient client = getClient(); retString = client.postMetadata(xmlMetadata); client.postUrl(identifier.substring(identifier.indexOf(":") + 1), target); @@ -182,7 +90,7 @@ public static String getMetadataFromDvObject(String identifier, Map metadata, DvObject dvObject) { - DataCiteMetadataTemplate metadataTemplate = new DataCiteMetadataTemplate(); + XmlMetadataTemplate metadataTemplate = new XmlMetadataTemplate(); metadataTemplate.setIdentifier(identifier.substring(identifier.indexOf(':') + 1)); metadataTemplate.setCreators(Arrays.asList(metadata.get("datacite.creator").split("; "))); @@ -256,7 +160,8 @@ public static String getMetadataForDeactivateIdentifier(String identifier, Map metadata, DvObject dvObject) throws IOException { + public String modifyIdentifier(String identifier, Map metadata, DvObject dvObject) + throws IOException { String xmlMetadata = getMetadataFromDvObject(identifier, metadata, dvObject); @@ -265,58 +170,26 @@ public String modifyIdentifier(String identifier, HashMap metada String status = metadata.get("_status").trim(); String target = metadata.get("_target"); String retString = ""; - if (status.equals("reserved")) { - DOIDataCiteRegisterCache rc = findByDOI(identifier); - if (rc == null) { - rc = new DOIDataCiteRegisterCache(); - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("reserved"); - rc.setUrl(target); - em.persist(rc); - } else { - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("reserved"); - rc.setUrl(target); - } + switch (status) { + case DataCiteDOIProvider.DRAFT: + // draft DOIs aren't currently being updated after every edit - ToDo - should + // this be changed or made optional? retString = "success to reserved " + identifier; - } else if (status.equals("public")) { - DOIDataCiteRegisterCache rc = findByDOI(identifier); - if (rc != null) { - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("public"); - if (target == null || target.trim().length() == 0) { - target = rc.getUrl(); - } else { - rc.setUrl(target); - } - try { - DataCiteRESTfullClient client = getClient(); - retString = client.postMetadata(xmlMetadata); - client.postUrl(identifier.substring(identifier.indexOf(":") + 1), target); - - } catch (UnsupportedEncodingException ex) { - logger.log(Level.SEVERE, null, ex); - - } catch (RuntimeException rte) { - logger.log(Level.SEVERE, "Error creating DOI at DataCite: {0}", rte.getMessage()); - logger.log(Level.SEVERE, "Exception", rte); - - } - } - } else if (status.equals("unavailable")) { - DOIDataCiteRegisterCache rc = findByDOI(identifier); + break; + case DataCiteDOIProvider.FINDABLE: try { - DataCiteRESTfullClient client = getClient(); - if (rc != null) { - rc.setStatus("unavailable"); - retString = client.inactiveDataset(identifier.substring(identifier.indexOf(":") + 1)); - } - } catch (IOException io) { - + retString = client.postMetadata(xmlMetadata); + client.postUrl(identifier.substring(identifier.indexOf(":") + 1), target); + } catch (UnsupportedEncodingException ex) { + logger.log(Level.SEVERE, null, ex); + } catch (RuntimeException rte) { + logger.log(Level.SEVERE, "Error creating DOI at DataCite: {0}", rte.getMessage()); + logger.log(Level.SEVERE, "Exception", rte); } + break; + case DataCiteDOIProvider.REGISTERED: + retString = client.inactiveDataset(identifier.substring(identifier.indexOf(":") + 1)); + break; } return retString; } @@ -324,7 +197,6 @@ public String modifyIdentifier(String identifier, HashMap metada public boolean testDOIExists(String identifier) { boolean doiExists; try { - DataCiteRESTfullClient client = getClient(); doiExists = client.testDOIExists(identifier.substring(identifier.indexOf(":") + 1)); } catch (Exception e) { logger.log(Level.INFO, identifier, e); @@ -333,326 +205,18 @@ public boolean testDOIExists(String identifier) { return doiExists; } - public HashMap getMetadata(String identifier) throws IOException { - HashMap metadata = new HashMap<>(); + Map getMetadata(String identifier) throws IOException { + Map metadata = new HashMap<>(); try { - DataCiteRESTfullClient client = getClient(); String xmlMetadata = client.getMetadata(identifier.substring(identifier.indexOf(":") + 1)); - AbstractPidProvider.GlobalIdMetadataTemplate template = doiDataCiteServiceBean.new GlobalIdMetadataTemplate(xmlMetadata); + XmlMetadataTemplate template = new XmlMetadataTemplate(xmlMetadata); metadata.put("datacite.creator", String.join("; ", template.getCreators())); metadata.put("datacite.title", template.getTitle()); metadata.put("datacite.publisher", template.getPublisher()); metadata.put("datacite.publicationyear", template.getPublisherYear()); - DOIDataCiteRegisterCache rc = findByDOI(identifier); - if (rc != null) { - metadata.put("_status", rc.getStatus()); - } else { - metadata.put("_status", "public"); - } } catch (RuntimeException e) { logger.log(Level.INFO, identifier, e); } return metadata; } - - public DOIDataCiteRegisterCache findByDOI(String doi) { - TypedQuery query = em.createNamedQuery("DOIDataCiteRegisterCache.findByDoi", - DOIDataCiteRegisterCache.class); - query.setParameter("doi", doi); - List rc = query.getResultList(); - if (rc.size() == 1) { - return rc.get(0); - } - return null; - } - - public void deleteIdentifier(String identifier) { - DOIDataCiteRegisterCache rc = findByDOI(identifier); - if (rc != null) { - em.remove(rc); - } - } - -} - -class DataCiteMetadataTemplate { - - private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.DataCiteMetadataTemplate"); - private static String template; - - static { - try (InputStream in = DataCiteMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { - template = new String(in.readAllBytes(),StandardCharsets.UTF_8); - } catch (Exception e) { - logger.log(Level.SEVERE, "datacite metadata template load error"); - logger.log(Level.SEVERE, "String " + e.toString()); - logger.log(Level.SEVERE, "localized message " + e.getLocalizedMessage()); - logger.log(Level.SEVERE, "cause " + e.getCause()); - logger.log(Level.SEVERE, "message " + e.getMessage()); - } - } - - private String xmlMetadata; - private String identifier; - private String datasetIdentifier; - private List datafileIdentifiers; - private List creators; - private String title; - private String publisher; - private String publisherYear; - private List authors; - private String description; - private List contacts; - private List producers; - - public List getProducers() { - return producers; - } - - public void setProducers(List producers) { - this.producers = producers; - } - - public List getContacts() { - return contacts; - } - - public void setContacts(List contacts) { - this.contacts = contacts; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public DataCiteMetadataTemplate() { - } - - public List getDatafileIdentifiers() { - return datafileIdentifiers; - } - - public void setDatafileIdentifiers(List datafileIdentifiers) { - this.datafileIdentifiers = datafileIdentifiers; - } - - public DataCiteMetadataTemplate(String xmlMetaData) { - this.xmlMetadata = xmlMetaData; - Document doc = Jsoup.parseBodyFragment(xmlMetaData); - Elements identifierElements = doc.select("identifier"); - if (identifierElements.size() > 0) { - identifier = identifierElements.get(0).html(); - } - Elements creatorElements = doc.select("creatorName"); - creators = new ArrayList<>(); - for (Element creatorElement : creatorElements) { - creators.add(creatorElement.html()); - } - Elements titleElements = doc.select("title"); - if (titleElements.size() > 0) { - title = titleElements.get(0).html(); - } - Elements publisherElements = doc.select("publisher"); - if (publisherElements.size() > 0) { - publisher = publisherElements.get(0).html(); - } - Elements publisherYearElements = doc.select("publicationYear"); - if (publisherYearElements.size() > 0) { - publisherYear = publisherYearElements.get(0).html(); - } - } - - public String generateXML(DvObject dvObject) { - // Can't use "UNKNOWN" here because DataCite will respond with "[facet 'pattern'] the value 'unknown' is not accepted by the pattern '[\d]{4}'" - String publisherYearFinal = "9999"; - // FIXME: Investigate why this.publisherYear is sometimes null now that pull request #4606 has been merged. - if (this.publisherYear != null) { - // Added to prevent a NullPointerException when trying to destroy datasets when using DataCite rather than EZID. - publisherYearFinal = this.publisherYear; - } - xmlMetadata = template.replace("${identifier}", this.identifier.trim()) - .replace("${title}", this.title) - .replace("${publisher}", this.publisher) - .replace("${publisherYear}", publisherYearFinal) - .replace("${description}", this.description); - - StringBuilder creatorsElement = new StringBuilder(); - if (authors!= null && !authors.isEmpty()) { - for (DatasetAuthor author : authors) { - creatorsElement.append(""); - creatorsElement.append(author.getName().getDisplayValue()); - creatorsElement.append(""); - - if (author.getIdType() != null && author.getIdValue() != null && !author.getIdType().isEmpty() && !author.getIdValue().isEmpty() && author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { - - if (author.getIdType().equals("ORCID")) { - creatorsElement.append("" + author.getIdValue() + ""); - } - if (author.getIdType().equals("ISNI")) { - creatorsElement.append("" + author.getIdValue() + ""); - } - if (author.getIdType().equals("LCNA")) { - creatorsElement.append("" + author.getIdValue() + ""); - } - } - if (author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { - creatorsElement.append("" + author.getAffiliation().getDisplayValue() + ""); - } - creatorsElement.append(""); - } - - } else { - creatorsElement.append("").append(AbstractPidProvider.UNAVAILABLE).append(""); - } - - xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); - - StringBuilder contributorsElement = new StringBuilder(); - if (this.getContacts() != null) { - for (String[] contact : this.getContacts()) { - if (!contact[0].isEmpty()) { - contributorsElement.append("" + contact[0] + ""); - if (!contact[1].isEmpty()) { - contributorsElement.append("" + contact[1] + ""); - } - contributorsElement.append(""); - } - } - } - - if (this.getProducers() != null) { - for (String[] producer : this.getProducers()) { - contributorsElement.append("" + producer[0] + ""); - if (!producer[1].isEmpty()) { - contributorsElement.append("" + producer[1] + ""); - } - contributorsElement.append(""); - } - } - - String relIdentifiers = generateRelatedIdentifiers(dvObject); - - xmlMetadata = xmlMetadata.replace("${relatedIdentifiers}", relIdentifiers); - - xmlMetadata = xmlMetadata.replace("{$contributors}", contributorsElement.toString()); - return xmlMetadata; - } - - private String generateRelatedIdentifiers(DvObject dvObject) { - - StringBuilder sb = new StringBuilder(); - if (dvObject.isInstanceofDataset()) { - Dataset dataset = (Dataset) dvObject; - if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { - - datafileIdentifiers = new ArrayList<>(); - for (DataFile dataFile : dataset.getFiles()) { - if (dataFile.getGlobalId() != null) { - if (sb.toString().isEmpty()) { - sb.append(""); - } - sb.append("" + dataFile.getGlobalId() + ""); - } - } - - if (!sb.toString().isEmpty()) { - sb.append(""); - } - } - } else if (dvObject.isInstanceofDataFile()) { - DataFile df = (DataFile) dvObject; - sb.append(""); - sb.append("" + df.getOwner().getGlobalId() + ""); - sb.append(""); - } - return sb.toString(); - } - - public void generateFileIdentifiers(DvObject dvObject) { - - if (dvObject.isInstanceofDataset()) { - Dataset dataset = (Dataset) dvObject; - - if (!dataset.getFiles().isEmpty() && !(dataset.getFiles().get(0).getIdentifier() == null)) { - - datafileIdentifiers = new ArrayList<>(); - for (DataFile dataFile : dataset.getFiles()) { - datafileIdentifiers.add(dataFile.getIdentifier()); - int x = xmlMetadata.indexOf("") - 1; - xmlMetadata = xmlMetadata.replace("{relatedIdentifier}", dataFile.getIdentifier()); - xmlMetadata = xmlMetadata.substring(0, x) + "${relatedIdentifier}" + template.substring(x, template.length() - 1); - - } - - } else { - xmlMetadata = xmlMetadata.replace("${relatedIdentifier}", ""); - } - } - } - - public static String getTemplate() { - return template; - } - - public static void setTemplate(String template) { - DataCiteMetadataTemplate.template = template; - } - - public String getIdentifier() { - return identifier; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } - - public void setDatasetIdentifier(String datasetIdentifier) { - this.datasetIdentifier = datasetIdentifier; - } - - public List getCreators() { - return creators; - } - - public void setCreators(List creators) { - this.creators = creators; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getPublisher() { - return publisher; - } - - public void setPublisher(String publisher) { - this.publisher = publisher; - } - - public String getPublisherYear() { - return publisherYear; - } - - public void setPublisherYear(String publisherYear) { - this.publisherYear = publisherYear; - } } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java index 4cbfbc7cc14..cf5c31d00c5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java @@ -10,13 +10,13 @@ import java.util.logging.Level; import java.util.logging.Logger; -import jakarta.ejb.EJB; -import jakarta.ejb.Stateless; +import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.pidproviders.doi.AbstractDOIProvider; -import edu.harvard.iq.dataverse.settings.JvmSettings; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; @@ -28,20 +28,20 @@ public class DataCiteDOIProvider extends AbstractDOIProvider { private static final Logger logger = Logger.getLogger(DataCiteDOIProvider.class.getCanonicalName()); - private static final String PUBLIC = "public"; - private static final String FINDABLE = "findable"; - private static final String RESERVED = "reserved"; - private static final String DRAFT = "draft"; + static final String FINDABLE = "findable"; //public - published dataset versions + static final String DRAFT = "draft"; //reserved but not findable yet - draft/unpublished datasets + static final String REGISTERED = "registered"; //was findable once, not anymore - deaccessioned datasets + static final String NONE = "none"; //no record - draft/unpublished datasets where the initial request to reserve has failed public static final String TYPE = "datacite"; - @EJB - DOIDataCiteRegisterService doiDataCiteRegisterService; private String mdsUrl; private String apiUrl; private String username; private String password; + + private DOIDataCiteRegisterService doiDataCiteRegisterService; public DataCiteDOIProvider(String id, String label, String providerAuthority, String providerShoulder, String identifierGenerationStyle, String datafilePidFormat, String managedList, String excludedList, @@ -52,6 +52,7 @@ public DataCiteDOIProvider(String id, String label, String providerAuthority, St this.apiUrl = apiUrl; this.username = username; this.password = password; + doiDataCiteRegisterService = new DOIDataCiteRegisterService(mdsUrl, username, password); } @Override @@ -103,6 +104,7 @@ public Map getIdentifierMetadata(DvObject dvObject) { Map metadata = new HashMap<>(); try { metadata = doiDataCiteRegisterService.getMetadata(identifier); + metadata.put("_status", getPidStatus(dvObject)); } catch (Exception e) { logger.log(Level.WARNING, "getIdentifierMetadata failed", e); } @@ -121,7 +123,7 @@ public String modifyIdentifierTargetURL(DvObject dvObject) throws Exception { logger.log(Level.FINE, "modifyIdentifier"); String identifier = getIdentifier(dvObject); try { - HashMap metadata = doiDataCiteRegisterService.getMetadata(identifier); + Map metadata = getIdentifierMetadata(dvObject); doiDataCiteRegisterService.modifyIdentifier(identifier, metadata, dvObject); } catch (Exception e) { logger.log(Level.WARNING, "modifyMetadata failed", e); @@ -130,74 +132,32 @@ public String modifyIdentifierTargetURL(DvObject dvObject) throws Exception { return identifier; } - public void deleteRecordFromCache(Dataset datasetIn) { - logger.log(Level.FINE, "deleteRecordFromCache"); - String identifier = getIdentifier(datasetIn); - HashMap doiMetadata = new HashMap(); - try { - doiMetadata = doiDataCiteRegisterService.getMetadata(identifier); - } catch (Exception e) { - logger.log(Level.WARNING, "get matadata failed cannot delete"); - logger.log(Level.WARNING, "String {0}", e.toString()); - logger.log(Level.WARNING, "localized message {0}", e.getLocalizedMessage()); - logger.log(Level.WARNING, "cause", e.getCause()); - logger.log(Level.WARNING, "message {0}", e.getMessage()); - } - - String idStatus = (String) doiMetadata.get("_status"); - - if (idStatus == null || idStatus.equals("reserved")) { - logger.log(Level.WARNING, "Delete status is reserved.."); - try { - doiDataCiteRegisterService.deleteIdentifier(identifier); - } catch (Exception e) { - logger.log(Level.WARNING, "delete failed"); - logger.log(Level.WARNING, "String {0}", e.toString()); - logger.log(Level.WARNING, "localized message {0}", e.getLocalizedMessage()); - logger.log(Level.WARNING, "cause", e.getCause()); - logger.log(Level.WARNING, "message {0}", e.getMessage()); - throw new RuntimeException(e); - } - } - } - /* - * Deletes a DOI if it is in DRAFT/RESERVED state or removes metadata and + * Deletes a DOI if it is in DRAFT/DRAFT state or removes metadata and * changes it from PUBLIC/FINDABLE to REGISTERED. */ @Override public void deleteIdentifier(DvObject dvObject) throws IOException, HttpException { logger.log(Level.FINE, "deleteIdentifier"); String identifier = getIdentifier(dvObject); - // ToDo - PidUtils currently has a DataCite API call that would get the status - // at DataCite for this identifier - that could be more accurate than assuming - // based on whether the dvObject has been published - String idStatus = DRAFT; - if (dvObject.isReleased()) { - idStatus = PUBLIC; - } - if (idStatus != null) { - switch (idStatus) { - case RESERVED: - case DRAFT: - logger.log(Level.INFO, "Delete status is reserved.."); - // service only removes the identifier from the cache (since it was written - // before DOIs could be registered in draft state) - doiDataCiteRegisterService.deleteIdentifier(identifier); - // So we call the deleteDraftIdentifier method below until things are refactored - deleteDraftIdentifier(dvObject); - break; + String idStatus = getPidStatus(dvObject); + switch (idStatus) { + case DRAFT: + logger.log(Level.FINE, "Delete status is reserved.."); + deleteDraftIdentifier(dvObject); + break; + case FINDABLE: + // if public then it has been released set to REGISTERED/unavailable and reset + // target to n2t url + Map metadata = addDOIMetadataForDestroyedDataset(dvObject); + metadata.put("_status", "registered"); + metadata.put("_target", getTargetUrl(dvObject)); + doiDataCiteRegisterService.deactivateIdentifier(identifier, metadata, dvObject); + break; - case PUBLIC: - case FINDABLE: - // if public then it has been released set to unavailable and reset target to - // n2t url - Map metadata = addDOIMetadataForDestroyedDataset(dvObject); - metadata.put("_status", "registered"); - metadata.put("_target", getTargetUrl(dvObject)); - doiDataCiteRegisterService.deactivateIdentifier(identifier, metadata, dvObject); - break; - } + case REGISTERED: + case NONE: + // Nothing to do } } @@ -207,10 +167,6 @@ public void deleteIdentifier(DvObject dvObject) throws IOException, HttpExceptio */ private void deleteDraftIdentifier(DvObject dvObject) throws IOException { - // ToDo - incorporate into DataCiteRESTfulClient - String baseUrl = JvmSettings.DATACITE_REST_API_URL.lookup("datacite"); - String username = JvmSettings.DATACITE_USERNAME.lookup("datacite"); - String password = JvmSettings.DATACITE_PASSWORD.lookup("datacite"); GlobalId doi = dvObject.getGlobalId(); /** * Deletes the DOI from DataCite if it can. Returns 204 if PID was deleted (only @@ -219,11 +175,11 @@ private void deleteDraftIdentifier(DvObject dvObject) throws IOException { * found, and possibly other status codes such as 500 if DataCite is down. */ - URL url = new URL(baseUrl + "/dois/" + doi.getAuthority() + "/" + doi.getIdentifier()); + URL url = new URL(getApiUrl() + "/dois/" + doi.getAuthority() + "/" + doi.getIdentifier()); HttpURLConnection connection = null; connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("DELETE"); - String userpass = username + ":" + password; + String userpass = getUsername() + ":" + getPassword(); String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes())); connection.setRequestProperty("Authorization", basicAuth); int status = connection.getResponseCode(); @@ -243,7 +199,7 @@ public boolean publicizeIdentifier(DvObject dvObject) { } String identifier = getIdentifier(dvObject); Map metadata = getUpdateMetadata(dvObject); - metadata.put("_status", PUBLIC); + metadata.put("_status", FINDABLE); metadata.put("datacite.publicationyear", generateYear(dvObject)); metadata.put("_target", getTargetUrl(dvObject)); try { @@ -287,4 +243,77 @@ public String getPassword() { return password; } + /** + * Method to determine the status of a dvObject's PID. It replaces keeping a + * separate DOIDataCiteRegisterCache. We could also try to get this info from + * DataCite directly, but it appears to not be in the xml metadata return, so it + * would require another/different api call (possible ToDo). + * + * @param dvObject - Dataset or DataFile + * @return PID status - NONE, DRAFT, FINDABLE, or REGISTERED + */ + private String getPidStatus(DvObject dvObject) { + String status = NONE; + if (dvObject instanceof Dataset) { + Dataset dataset = (Dataset) dvObject; + // return true, if all published versions were deaccessioned + boolean hasDeaccessionedVersions = false; + for (DatasetVersion testDsv : dataset.getVersions()) { + if (testDsv.isReleased()) { + // With any released version, we're done + return FINDABLE; + } + // Also check for draft version + if (testDsv.isDraft()) { + if (dataset.isIdentifierRegistered()) { + status = DRAFT; + // Keep interating to see if there's a released version + } + } + if (testDsv.isDeaccessioned()) { + hasDeaccessionedVersions = true; + // Keep interating to see if there's a released version + } + } + if (hasDeaccessionedVersions) { + if (dataset.isIdentifierRegistered()) { + return REGISTERED; + } + } + return status; + } else if (dvObject instanceof DataFile) { + DataFile df = (DataFile) dvObject; + // return true, if all published versions were deaccessioned + boolean isInDeaccessionedVersions = false; + for (FileMetadata fmd : df.getFileMetadatas()) { + DatasetVersion testDsv = fmd.getDatasetVersion(); + if (testDsv.isReleased()) { + // With any released version, we're done + return FINDABLE; + } + // Also check for draft version + if (testDsv.isDraft()) { + if (df.isIdentifierRegistered()) { + status = DRAFT; + // Keep interating to see if there's a released/deaccessioned version + } + } + if (testDsv.isDeaccessioned()) { + isInDeaccessionedVersions = true; + // Keep interating to see if there's a released version + } + } + if (isInDeaccessionedVersions) { + if (df.isIdentifierRegistered()) { + return REGISTERED; + } + } + + } + return status; + } + + + + } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java index 771aa781876..d185b0249b9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteRESTfullClient.java @@ -45,21 +45,14 @@ public class DataCiteRESTfullClient implements Closeable { private HttpClientContext context; private String encoding = "utf-8"; - public DataCiteRESTfullClient(String url, String username, String password) throws IOException { + public DataCiteRESTfullClient(String url, String username, String password) { this.url = url; - try { - context = HttpClientContext.create(); - CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials(new AuthScope(null, -1), - new UsernamePasswordCredentials(username, password)); - context.setCredentialsProvider(credsProvider); - - httpClient = HttpClients.createDefault(); - } catch (Exception ioe) { - close(); - logger.log(Level.SEVERE,"Fail to init Client",ioe); - throw new RuntimeException("Fail to init Client", ioe); - } + context = HttpClientContext.create(); + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(username, password)); + context.setCredentialsProvider(credsProvider); + + httpClient = HttpClients.createDefault(); } public void close() { From fcdf74dbe8c9c72a8ccbc12e0b502c96ee491297 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 16 Feb 2024 14:12:37 -0500 Subject: [PATCH 094/113] moving XmlMetadataTemplate to doi package --- .../pidproviders/AbstractPidProvider.java | 37 -------------- .../pidproviders/PidProviderFactoryBean.java | 2 +- .../pidproviders/doi/AbstractDOIProvider.java | 50 +++++++++++++++++++ .../{ => doi}/XmlMetadataTemplate.java | 2 +- .../datacite/DOIDataCiteRegisterService.java | 2 +- .../doi/ezid/EZIdDOIProvider.java | 2 +- 6 files changed, 54 insertions(+), 41 deletions(-) rename src/main/java/edu/harvard/iq/dataverse/pidproviders/{ => doi}/XmlMetadataTemplate.java (97%) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java index dfee7ce21dd..a3dcf6cbb3b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java @@ -456,43 +456,6 @@ private String generateIdentifierFromStoredProcedureDependent(DataFile datafile, return identifier; } - public String getMetadataFromDvObject(String identifier, Map metadata, DvObject dvObject) { - - Dataset dataset = null; - - if (dvObject instanceof Dataset) { - dataset = (Dataset) dvObject; - } else { - dataset = (Dataset) dvObject.getOwner(); - } - - XmlMetadataTemplate metadataTemplate = new XmlMetadataTemplate(); - metadataTemplate.setIdentifier(identifier.substring(identifier.indexOf(':') + 1)); - metadataTemplate.setCreators(Arrays.asList(metadata.get("datacite.creator").split("; "))); - metadataTemplate.setAuthors(dataset.getLatestVersion().getDatasetAuthors()); - if (dvObject.isInstanceofDataset()) { - metadataTemplate.setDescription(dataset.getLatestVersion().getDescriptionPlainText()); - } - if (dvObject.isInstanceofDataFile()) { - DataFile df = (DataFile) dvObject; - String fileDescription = df.getDescription(); - metadataTemplate.setDescription(fileDescription == null ? "" : fileDescription); - } - - metadataTemplate.setContacts(dataset.getLatestVersion().getDatasetContacts()); - metadataTemplate.setProducers(dataset.getLatestVersion().getDatasetProducers()); - metadataTemplate.setTitle(dvObject.getCurrentName()); - String producerString = pidProviderService.getProducer(); - if (producerString.isEmpty() || producerString.equals(DatasetField.NA_VALUE)) { - producerString = UNAVAILABLE; - } - metadataTemplate.setPublisher(producerString); - metadataTemplate.setPublisherYear(metadata.get("datacite.publicationyear")); - - String xmlMetadata = metadataTemplate.generateXML(dvObject); - logger.log(Level.FINE, "XML to send to DataCite: {0}", xmlMetadata); - return xmlMetadata; - } @Override public boolean canManagePID() { diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 89f8fc5f04e..7d6e5f57ea9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -220,7 +220,7 @@ private void loadProviders() { new UnmanagedHandlePidProvider(), new UnmanagedPermaLinkPidProvider())); } - String getProducer() { + public String getProducer() { return dataverseService.getRootDataverseName(); } diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java index 7a0ea052fb3..43e34e74c59 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/AbstractDOIProvider.java @@ -1,5 +1,14 @@ package edu.harvard.iq.dataverse.pidproviders.doi; +import java.util.Arrays; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetField; +import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; import edu.harvard.iq.dataverse.pidproviders.PidProvider; @@ -7,6 +16,8 @@ public abstract class AbstractDOIProvider extends AbstractPidProvider { + private static final Logger logger = Logger.getLogger(AbstractDOIProvider.class.getCanonicalName()); + public static final String DOI_PROTOCOL = "doi"; public static final String DOI_RESOLVER_URL = "https://doi.org/"; public static final String HTTP_DOI_RESOLVER_URL = "http://doi.org/"; @@ -70,4 +81,43 @@ protected String getProviderKeyName() { public String getProtocol() { return DOI_PROTOCOL; } + + public String getMetadataFromDvObject(String identifier, Map metadata, DvObject dvObject) { + + Dataset dataset = null; + + if (dvObject instanceof Dataset) { + dataset = (Dataset) dvObject; + } else { + dataset = (Dataset) dvObject.getOwner(); + } + + XmlMetadataTemplate metadataTemplate = new XmlMetadataTemplate(); + metadataTemplate.setIdentifier(identifier.substring(identifier.indexOf(':') + 1)); + metadataTemplate.setCreators(Arrays.asList(metadata.get("datacite.creator").split("; "))); + metadataTemplate.setAuthors(dataset.getLatestVersion().getDatasetAuthors()); + if (dvObject.isInstanceofDataset()) { + metadataTemplate.setDescription(dataset.getLatestVersion().getDescriptionPlainText()); + } + if (dvObject.isInstanceofDataFile()) { + DataFile df = (DataFile) dvObject; + String fileDescription = df.getDescription(); + metadataTemplate.setDescription(fileDescription == null ? "" : fileDescription); + } + + metadataTemplate.setContacts(dataset.getLatestVersion().getDatasetContacts()); + metadataTemplate.setProducers(dataset.getLatestVersion().getDatasetProducers()); + metadataTemplate.setTitle(dvObject.getCurrentName()); + String producerString = pidProviderService.getProducer(); + if (producerString.isEmpty() || producerString.equals(DatasetField.NA_VALUE)) { + producerString = UNAVAILABLE; + } + metadataTemplate.setPublisher(producerString); + metadataTemplate.setPublisherYear(metadata.get("datacite.publicationyear")); + + String xmlMetadata = metadataTemplate.generateXML(dvObject); + logger.log(Level.FINE, "XML to send to DataCite: {0}", xmlMetadata); + return xmlMetadata; + } + } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java similarity index 97% rename from src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java rename to src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java index d91c382995f..639feadaac9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/XmlMetadataTemplate.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java @@ -1,4 +1,4 @@ -package edu.harvard.iq.dataverse.pidproviders; +package edu.harvard.iq.dataverse.pidproviders.doi; import java.io.InputStream; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java index d67ce72976f..0e322eace05 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DOIDataCiteRegisterService.java @@ -21,7 +21,7 @@ import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; -import edu.harvard.iq.dataverse.pidproviders.XmlMetadataTemplate; +import edu.harvard.iq.dataverse.pidproviders.doi.XmlMetadataTemplate; /** * diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java index 75e88de0d34..fe8f1ec9c70 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdDOIProvider.java @@ -276,7 +276,7 @@ public String createIdentifier(DvObject dvObject) throws Throwable { * @return A HashMap with the same values as {@code map} */ private HashMap asHashMap(Map map) { - return (map instanceof HashMap) ? (HashMap)map : new HashMap<>(map); + return (map instanceof HashMap) ? (HashMap)map : new HashMap<>(map); } @Override From 967009eab7a3c75cd1c3987c0407308399d1fbef Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 16 Feb 2024 14:23:11 -0500 Subject: [PATCH 095/113] missing import --- .../iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java index 639feadaac9..30e4dfd79cc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/XmlMetadataTemplate.java @@ -16,6 +16,7 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetAuthor; import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider; public class XmlMetadataTemplate { From d539d138ace99b1b6c658b47c03bee74bff0f87c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 16 Feb 2024 15:24:29 -0500 Subject: [PATCH 096/113] move xml file to match package --- .../pidproviders/{datacite => doi}/datacite_metadata_template.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/edu/harvard/iq/dataverse/pidproviders/{datacite => doi}/datacite_metadata_template.xml (100%) diff --git a/src/main/resources/edu/harvard/iq/dataverse/pidproviders/datacite/datacite_metadata_template.xml b/src/main/resources/edu/harvard/iq/dataverse/pidproviders/doi/datacite_metadata_template.xml similarity index 100% rename from src/main/resources/edu/harvard/iq/dataverse/pidproviders/datacite/datacite_metadata_template.xml rename to src/main/resources/edu/harvard/iq/dataverse/pidproviders/doi/datacite_metadata_template.xml From b80ed820758d9e3c04916d0cbb477560afe44830 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 20 Feb 2024 13:36:58 -0500 Subject: [PATCH 097/113] minor fixes, make getPidStatus visible in test --- .../pidproviders/doi/datacite/DataCiteDOIProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java index cf5c31d00c5..23078e2719b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java @@ -86,7 +86,7 @@ public String createIdentifier(DvObject dvObject) throws Exception { } String identifier = getIdentifier(dvObject); Map metadata = getMetadataForCreateIndicator(dvObject); - metadata.put("_status", "reserved"); + metadata.put("_status", DRAFT); try { String retString = doiDataCiteRegisterService.reserveIdentifier(identifier, metadata, dvObject); logger.log(Level.FINE, "create DOI identifier retString : " + retString); @@ -252,7 +252,7 @@ public String getPassword() { * @param dvObject - Dataset or DataFile * @return PID status - NONE, DRAFT, FINDABLE, or REGISTERED */ - private String getPidStatus(DvObject dvObject) { + String getPidStatus(DvObject dvObject) { String status = NONE; if (dvObject instanceof Dataset) { Dataset dataset = (Dataset) dvObject; From 3854e52afe394a954da73b783972b43f5d428c9b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 20 Feb 2024 13:37:12 -0500 Subject: [PATCH 098/113] disabled test of DPI lifecycle --- .../doi/datacite/DataCiteProviderTest.java | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 src/test/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderTest.java diff --git a/src/test/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderTest.java b/src/test/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderTest.java new file mode 100644 index 00000000000..572fc722272 --- /dev/null +++ b/src/test/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteProviderTest.java @@ -0,0 +1,187 @@ +package edu.harvard.iq.dataverse.pidproviders.doi.datacite; + +import edu.harvard.iq.dataverse.Dataset; +import edu.harvard.iq.dataverse.DatasetField; +import edu.harvard.iq.dataverse.DatasetFieldConstant; +import edu.harvard.iq.dataverse.DatasetFieldType; +import edu.harvard.iq.dataverse.DatasetVersion; +import edu.harvard.iq.dataverse.DatasetVersion.VersionState; +import edu.harvard.iq.dataverse.DataverseServiceBean; +import edu.harvard.iq.dataverse.GlobalId; +import edu.harvard.iq.dataverse.branding.BrandingUtil; +import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; +import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import edu.harvard.iq.dataverse.util.SystemConfig; +import edu.harvard.iq.dataverse.util.testing.JvmSetting; +import edu.harvard.iq.dataverse.util.testing.LocalJvmSettings; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; + +@ExtendWith(MockitoExtension.class) +@LocalJvmSettings +@JvmSetting(key = JvmSettings.SITE_URL, value = "https://example.com") + +public class DataCiteProviderTest { + + static DataverseServiceBean dataverseSvc; + static SettingsServiceBean settingsSvc; + static PidProviderFactoryBean pidService; + static final String DEFAULT_NAME = "LibraScholar"; + + @BeforeAll + public static void setupMocks() { + dataverseSvc = Mockito.mock(DataverseServiceBean.class); + settingsSvc = Mockito.mock(SettingsServiceBean.class); + BrandingUtil.injectServices(dataverseSvc, settingsSvc); + + // initial values (needed here for other tests where this method is reused!) + Mockito.when(settingsSvc.getValueForKey(SettingsServiceBean.Key.InstallationName)).thenReturn(DEFAULT_NAME); + Mockito.when(dataverseSvc.getRootDataverseName()).thenReturn(DEFAULT_NAME); + + pidService = Mockito.mock(PidProviderFactoryBean.class); + Mockito.when(pidService.isGlobalIdLocallyUnique(any(GlobalId.class))).thenReturn(true); + Mockito.when(pidService.getProducer()).thenReturn("RootDataverse"); + + } + + /** + * Useful for testing but requires DataCite credentials, etc. + * + * To run the test: + * export DataCiteUsername=test2 + * export DataCitePassword=changeme2 + * export DataCiteAuthority=10.5072 + * export DataCiteShoulder=FK2 + * + * then run mvn test -Dtest=DataCiteProviderTest + * + * For each run of the test, one test DOI will be created and will remain in the registered state, as visible on Fabrica at doi.test.datacite.org + * (two DOIs are created, but one is deleted after being created in the draft state and never made findable.) + */ + @Test + @Disabled + public void testDoiLifecycle() throws IOException { + String username = System.getenv("DataCiteUsername"); + String password = System.getenv("DataCitePassword"); + String authority = System.getenv("DataCiteAuthority"); + String shoulder = System.getenv("DataCiteShoulder"); + DataCiteDOIProvider provider = new DataCiteDOIProvider("test", "test", authority, shoulder, "randomString", + SystemConfig.DataFilePIDFormat.DEPENDENT.toString(), "", "", "https://mds.test.datacite.org", + "https://api.test.datacite.org", username, password); + + provider.setPidProviderServiceBean(pidService); + + PidUtil.addToProviderList(provider); + + Dataset d = new Dataset(); + DatasetVersion dv = new DatasetVersion(); + DatasetFieldType primitiveDSFType = new DatasetFieldType(DatasetFieldConstant.title, + DatasetFieldType.FieldType.TEXT, false); + DatasetField testDatasetField = new DatasetField(); + + dv.setVersionState(VersionState.DRAFT); + + testDatasetField.setDatasetVersion(dv); + testDatasetField.setDatasetFieldType(primitiveDSFType); + testDatasetField.setSingleValue("First Title"); + List fields = new ArrayList<>(); + fields.add(testDatasetField); + dv.setDatasetFields(fields); + ArrayList dsvs = new ArrayList<>(); + dsvs.add(0, dv); + d.setVersions(dsvs); + + assertEquals(d.getCurrentName(), "First Title"); + + provider.generatePid(d); + assertEquals(d.getProtocol(), "doi"); + assertEquals(d.getAuthority(), authority); + assertTrue(d.getIdentifier().startsWith(shoulder)); + d.getGlobalId(); + + try { + provider.createIdentifier(d); + d.setIdentifierRegistered(true); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + assertEquals(DataCiteDOIProvider.DRAFT, provider.getPidStatus(d)); + Map mdMap = provider.getIdentifierMetadata(d); + assertEquals("First Title", mdMap.get("datacite.title")); + + testDatasetField.setSingleValue("Second Title"); + + //Modify called for a draft dataset shouldn't update DataCite (given current code) + try { + provider.modifyIdentifierTargetURL(d); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //Verify the title hasn't changed + mdMap = provider.getIdentifierMetadata(d); + assertEquals("First Title", mdMap.get("datacite.title")); + //Check our local status + assertEquals(DataCiteDOIProvider.DRAFT, provider.getPidStatus(d)); + //Now delete the identifier + provider.deleteIdentifier(d); + //Causes a 404 and a caught exception that prints a stack trace. + mdMap = provider.getIdentifierMetadata(d); + // And verify the record is gone (no title, should be no entries at all) + assertEquals(null, mdMap.get("datacite.title")); + + //Now recreate and publicize in one step + assertTrue(provider.publicizeIdentifier(d)); + d.getLatestVersion().setVersionState(VersionState.RELEASED); + + //Verify the title hasn't changed + mdMap = provider.getIdentifierMetadata(d); + assertEquals("Second Title", mdMap.get("datacite.title")); + //Check our local status + assertEquals(DataCiteDOIProvider.FINDABLE, provider.getPidStatus(d)); + + //Verify that modify does update a published/findable record + testDatasetField.setSingleValue("Third Title"); + + try { + provider.modifyIdentifierTargetURL(d); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + mdMap = provider.getIdentifierMetadata(d); + assertEquals("Third Title", mdMap.get("datacite.title")); + + //Now delete the identifier . Once it's been findable, this should just flip the record to registered + //Not sure that can be easily verified in the test, but it will be visible in Fabrica + provider.deleteIdentifier(d); + d.getLatestVersion().setVersionState(VersionState.DEACCESSIONED); + + mdMap = provider.getIdentifierMetadata(d); + assertEquals("This item has been removed from publication", mdMap.get("datacite.title")); + + //Check our local status - just uses the version state + assertEquals(DataCiteDOIProvider.REGISTERED, provider.getPidStatus(d)); + + // provider.registerWhenPublished() + } + +} From ae963d563ca51583e070aa51abad937867292841 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 20 Feb 2024 14:44:46 -0500 Subject: [PATCH 099/113] update installer/docs to not talk about a partial DataCite test setup --- .../source/installation/config.rst | 27 +++++++++++-------- scripts/dev/dev-rebuild.sh | 3 --- scripts/installer/as-setup.sh | 19 ++++++------- scripts/installer/install.py | 13 +++++---- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index e3b064c104a..4587c7b1e41 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -190,9 +190,11 @@ along with an optional list of individual PIDs (with different authority/shoulde Testing PID Providers +++++++++++++++++++++ -By default, the installer configures the DataCite test service as the registration provider. DataCite requires that you -register for a test account, configured with your own prefix (please contact support@datacite.org for a test account. Alternately, -you may wish to `contact the GDCC `_ - GDCC is able to provide DataCite accounts with a group discount and can also provide test accounts.). +By default, the installer configures the Fake DOI provider as the registration provider. Unlike other DOI Providers, the Fake Provider does not involve any +external resolution service and is not appropriate for use beyond development and testing. You may wish instead to test with +PermaLinks or with a DataCite test account (which uses DataCite's test infrastructure and will help assure your Dataverse instance can make network connections to DataCite. +DataCite requires that you register for a test account, which will have a username, password and your own prefix (please contact support@datacite.org for a test account. +You may wish to `contact the GDCC `_ instead - GDCC is able to provide DataCite accounts with a group discount and can also provide test accounts.). Once you receive the login name, password, and prefix for the account, configure the credentials as described below. @@ -201,24 +203,27 @@ Alternately, you may wish to configure other providers for testing: - EZID is available to University of California scholars and researchers. Testing can be done using the authority 10.5072 and shoulder FK2 with the "apitest" account (contact EZID for credentials) or an institutional account. Configuration in Dataverse is then analogous to using DataCite. - - The PermaLink and FAKE DOI providers do not involve an external account. The FAKE provider should only be used for testing, since it creates identifiers that look like DOIs but will not resolve. In contrast, the PermaLink provider creates PIDs that begin with "perma:", making it clearer that they are not DOIs, while they do resolve to the local dataset/file page in Dataverse. See :ref:`permalinks` and (for the FAKE DOI provider) the :doc:`/developers/dev-environment` section of the Developer Guide. + - The PermaLink provider, like the FAKE DOI provider, does not involve an external account. + Unlike the Fake DOI provider, the PermaLink provider creates PIDs that begin with "perma:", making it clearer that they are not DOIs, + and that do resolve to the local dataset/file page in Dataverse, making them useful for some production use cases. See :ref:`permalinks` and (for the FAKE DOI provider) the :doc:`/developers/dev-environment` section of the Developer Guide. Provider-specific configuration is described below. -Once all is configured, you will be able to publish datasets and files, but **the persistent identifiers will not be citable**, -e.g. they will only resolve from the DataCite test environment (and then only if the Dataverse installation from which -you published them is accessible - DOIs minted from your laptop will not resolve). Note that any datasets or files -created using the test configuration cannot be directly migrated and would need to be created again once a valid DOI -namespace is configured. +Once all is configured, you will be able to publish datasets and files, but **the persistent identifiers will not be citable** +as they, with the exception of PermaLinks, will not redirect to your dataset page in Dataverse. + +Note that any datasets or files created using a test configuration cannot be directly migrated to a production PID provider +and would need to be created again once a valid PID Provider(s) are configured. One you are done testing, to properly configure persistent identifiers for a production installation, an account and associated namespace (e.g. authority/shoulder) must be -acquired for a fee from a DOI or HDL provider. **DataCite** (https://www.datacite.org) is the recommended DOI provider +acquired for a fee from a DOI or HDL provider. (As noted above, PermaLinks May be appropriate for intranet and catalog uses cases.) +**DataCite** (https://www.datacite.org) is the recommended DOI provider (see https://dataversecommunity.global for more on joining DataCite through the Global Dataverse Community Consortium) but **EZID** (http://ezid.cdlib.org) is an option for the University of California according to https://www.cdlib.org/cdlinfo/2017/08/04/ezid-doi-service-is-evolving/ . **Handle.Net** (https://www.handle.net) is the HDL provider. -Once you have your DOI or Handle account credentials and a namespace, configure your Dataverse installation +Once you have your DOI or Handle account credentials and a prefix, configure your Dataverse installation using the settings below. diff --git a/scripts/dev/dev-rebuild.sh b/scripts/dev/dev-rebuild.sh index 9eae195b135..898212b4664 100755 --- a/scripts/dev/dev-rebuild.sh +++ b/scripts/dev/dev-rebuild.sh @@ -56,9 +56,6 @@ cd ../.. echo "Creating SQL sequence..." psql -h localhost -U $DB_USER $DB_NAME -f doc/sphinx-guides/source/_static/util/createsequence.sql -echo "Setting DOI provider to \"FAKE\"..." -curl http://localhost:8080/api/admin/settings/:DoiProvider -X PUT -d FAKE - echo "Allowing GUI edits to be visible without redeploy..." $PAYARA_DIR/glassfish/bin/asadmin create-system-properties "dataverse.jsf.refresh-period=1" diff --git a/scripts/installer/as-setup.sh b/scripts/installer/as-setup.sh index 53550800dd6..c89bcb4ff4d 100755 --- a/scripts/installer/as-setup.sh +++ b/scripts/installer/as-setup.sh @@ -102,21 +102,18 @@ function preliminary_setup() # password reset token timeout in minutes ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.auth.password-reset-timeout-in-minutes=60" - # DataCite DOI Settings + # Fake DOI Settings # (we can no longer offer EZID with their shared test account) # jvm-options use colons as separators, escape as literal DOI_BASEURL_ESC=`echo $DOI_BASEURL | sed -e 's/:/\\\:/'` - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.providers=testDC" - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.type=datacite" - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.label=TestDataCite" - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.authority=10.5072" - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.shoulder=FK2/" - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.username=${DOI_USERNAME}" - ./asadmin $ASADMIN_OPTS create-jvm-options '\-Ddataverse.pid.testDC.datacite.password=${ALIAS=doi_password_alias}' - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.mds-api-url=$DOI_BASEURL_ESC" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.providers=fake" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.fake.type=FAKE" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.fake.label=Fake DOI Provider" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.fake.authority=10.5072" + ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.fake.shoulder=FK2/" # jvm-options use colons as separators, escape as literal - DOI_DATACITERESTAPIURL_ESC=`echo $DOI_DATACITERESTAPIURL | sed -e 's/:/\\\:/'` - ./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.rest-api-url=$DOI_DATACITERESTAPIURL_ESC" + #DOI_DATACITERESTAPIURL_ESC=`echo $DOI_DATACITERESTAPIURL | sed -e 's/:/\\\:/'` + #./asadmin $ASADMIN_OPTS create-jvm-options "\-Ddataverse.pid.testDC.datacite.rest-api-url=$DOI_DATACITERESTAPIURL_ESC" ./asadmin $ASADMIN_OPTS create-jvm-options "-Ddataverse.timerServer=true" diff --git a/scripts/installer/install.py b/scripts/installer/install.py index 18995695638..b7da5333e47 100644 --- a/scripts/installer/install.py +++ b/scripts/installer/install.py @@ -591,15 +591,14 @@ print("\n\nYou should now have a running Dataverse instance at") print(" http://" + hostName + ":8080\n\n") -# DataCite instructions: +# PID instructions: -print("\nYour Dataverse has been configured to use DataCite, to register DOI global identifiers in the ") +print("\nYour Dataverse has been configured to use a Fake DOI Provider, registering (non-resolvable) DOI global identifiers in the ") print("test name space \"10.5072\" with the \"shoulder\" \"FK2\"") -print("However, you have to contact DataCite (support\@datacite.org) and request a test account, before you ") -print("can publish datasets. Once you receive the account name and password, add them to your domain.xml,") -print("as the following two JVM options:") -print("\t-Ddataverse.pid.datacite.username=...") -print("\t-Ddataverse.pid.datacite.password=...") +print("You can reconfigure to use additional/alternative providers." +print("If you intend to use DOIs, you should contact DataCite (support\@datacite.org) or GDCC (see https://www.gdcc.io/about.html) and request a test account.") +print("Once you receive the account information (name, password, authority, shoulder), add them to your configuration ") +print("as described in the Dataverse Guides (see https://guides.dataverse.org/en/latest/installation/config.html#persistent-identifiers-and-publishing-datasets),") print("and restart payara") print("If this is a production Dataverse and you are planning to register datasets as ") print("\"real\", non-test DOIs or Handles, consult the \"Persistent Identifiers and Publishing Datasets\"") From 03824d0b1be5d811eab4805bed2a70edec3d7b3e Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 20 Feb 2024 14:45:56 -0500 Subject: [PATCH 100/113] remove legacy setting --- scripts/deploy/phoenix.dataverse.org/post | 1 - scripts/dev/docker-final-setup.sh | 3 --- 2 files changed, 4 deletions(-) diff --git a/scripts/deploy/phoenix.dataverse.org/post b/scripts/deploy/phoenix.dataverse.org/post index e4c8817844b..9d37c183a1a 100755 --- a/scripts/deploy/phoenix.dataverse.org/post +++ b/scripts/deploy/phoenix.dataverse.org/post @@ -4,7 +4,6 @@ cd scripts/api cd ../.. psql -U dvnapp dvndb -f scripts/database/reference_data.sql psql -U dvnapp dvndb -f doc/sphinx-guides/source/_static/util/createsequence.sql -curl http://localhost:8080/api/admin/settings/:DoiProvider -X PUT -d FAKE scripts/search/tests/publish-dataverse-root git checkout scripts/api/data/dv-root.json scripts/search/tests/grant-authusers-add-on-root diff --git a/scripts/dev/docker-final-setup.sh b/scripts/dev/docker-final-setup.sh index d2453619ec2..e20ce7ad6b6 100755 --- a/scripts/dev/docker-final-setup.sh +++ b/scripts/dev/docker-final-setup.sh @@ -10,9 +10,6 @@ cd ../.. echo "Setting system mail address..." curl -X PUT -d "dataverse@localhost" "http://localhost:8080/api/admin/settings/:SystemEmail" -echo "Setting DOI provider to \"FAKE\"..." -curl "http://localhost:8080/api/admin/settings/:DoiProvider" -X PUT -d FAKE - API_TOKEN=$(grep apiToken "/tmp/setup-all.sh.out" | jq ".data.apiToken" | tr -d \") export API_TOKEN From 0193310767a6cf7a818c14276568453e207d57ce Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 20 Feb 2024 14:51:36 -0500 Subject: [PATCH 101/113] indent issue --- doc/sphinx-guides/source/installation/config.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 4587c7b1e41..6818ef77956 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -204,8 +204,8 @@ Alternately, you may wish to configure other providers for testing: - EZID is available to University of California scholars and researchers. Testing can be done using the authority 10.5072 and shoulder FK2 with the "apitest" account (contact EZID for credentials) or an institutional account. Configuration in Dataverse is then analogous to using DataCite. - The PermaLink provider, like the FAKE DOI provider, does not involve an external account. - Unlike the Fake DOI provider, the PermaLink provider creates PIDs that begin with "perma:", making it clearer that they are not DOIs, - and that do resolve to the local dataset/file page in Dataverse, making them useful for some production use cases. See :ref:`permalinks` and (for the FAKE DOI provider) the :doc:`/developers/dev-environment` section of the Developer Guide. + Unlike the Fake DOI provider, the PermaLink provider creates PIDs that begin with "perma:", making it clearer that they are not DOIs, + and that do resolve to the local dataset/file page in Dataverse, making them useful for some production use cases. See :ref:`permalinks` and (for the FAKE DOI provider) the :doc:`/developers/dev-environment` section of the Developer Guide. Provider-specific configuration is described below. From 958be0e0022218eb305cb9cc3cb0f0ca7f5f47c0 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 20 Feb 2024 15:54:15 -0500 Subject: [PATCH 102/113] missing ) --- scripts/installer/install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/installer/install.py b/scripts/installer/install.py index b7da5333e47..99316efb83b 100644 --- a/scripts/installer/install.py +++ b/scripts/installer/install.py @@ -595,7 +595,7 @@ print("\nYour Dataverse has been configured to use a Fake DOI Provider, registering (non-resolvable) DOI global identifiers in the ") print("test name space \"10.5072\" with the \"shoulder\" \"FK2\"") -print("You can reconfigure to use additional/alternative providers." +print("You can reconfigure to use additional/alternative providers.") print("If you intend to use DOIs, you should contact DataCite (support\@datacite.org) or GDCC (see https://www.gdcc.io/about.html) and request a test account.") print("Once you receive the account information (name, password, authority, shoulder), add them to your configuration ") print("as described in the Dataverse Guides (see https://guides.dataverse.org/en/latest/installation/config.html#persistent-identifiers-and-publishing-datasets),") From e02743a76c2107c63af7f1d8c6c81cc00207ecc8 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 22 Feb 2024 10:29:52 -0500 Subject: [PATCH 103/113] fix setting name --- doc/sphinx-guides/source/installation/config.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 6818ef77956..2baa2827250 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -271,10 +271,10 @@ dataverse.pid.default-provider The ID of the default PID provider to use. -.. _dataverse.pid.provider-implementations-directory: +.. _dataverse.spi.pidproviders.directory: -dataverse.pid.provider-implementations-directory -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +dataverse.spi.pidproviders.directory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The path to the directory where JAR files containing additional types of PID Providers can be added. Dataverse includes providers that support DOIs (DataCite, EZId, or FAKE), Handles, and PermaLinks. From 1acba08c7c57867a0b3d35084995ac663f75dddc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 22 Feb 2024 10:31:03 -0500 Subject: [PATCH 104/113] remove obsolete settings --- .../resources/META-INF/microprofile-config.properties | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/main/resources/META-INF/microprofile-config.properties b/src/main/resources/META-INF/microprofile-config.properties index 0a769e06573..56c0fe0ff0a 100644 --- a/src/main/resources/META-INF/microprofile-config.properties +++ b/src/main/resources/META-INF/microprofile-config.properties @@ -50,17 +50,6 @@ dataverse.oai.server.maxsets=100 # can be customized via the setting below: #dataverse.oai.server.repositoryname= -# PERSISTENT IDENTIFIER PROVIDERS -# EZID -dataverse.pid.ezid.ezid.api-url=https://ezid.cdlib.org - -# DataCite -dataverse.pid.datacite.datacite.mds-api-url=https://mds.test.datacite.org -dataverse.pid.datacite.datacite.rest-api-url=https://api.test.datacite.org - -# Handle.Net -dataverse.pid.handlenet.handlenet.index=300 - # AUTHENTICATION dataverse.auth.oidc.pkce.max-cache-size=10000 dataverse.auth.oidc.pkce.max-cache-age=300 From b8926dcfeb2b40af1ef8122d37ab52b909d629a3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 22 Feb 2024 10:47:27 -0500 Subject: [PATCH 105/113] add defaults --- .../iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java | 2 +- .../iq/dataverse/pidproviders/handle/HandleProviderFactory.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java index 6c9e6f06c6f..95ad9bdeff0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/ezid/EZIdProviderFactory.java @@ -27,7 +27,7 @@ public PidProvider createPidProvider(String providerId) { String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - String baseUrl = JvmSettings.EZID_API_URL.lookup(providerId); + String baseUrl = JvmSettings.EZID_API_URL.lookupOptional(providerId).orElse("https://ezid.cdlib.org"); String username = JvmSettings.EZID_USERNAME.lookup(providerId); String password = JvmSettings.EZID_PASSWORD.lookup(providerId); diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java index 9dd1c5f2928..eef5bed8432 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/handle/HandleProviderFactory.java @@ -27,7 +27,7 @@ public PidProvider createPidProvider(String providerId) { String managedList = JvmSettings.PID_PROVIDER_MANAGED_LIST.lookupOptional(providerId).orElse(""); String excludedList = JvmSettings.PID_PROVIDER_EXCLUDED_LIST.lookupOptional(providerId).orElse(""); - int index = JvmSettings.HANDLENET_INDEX.lookup(Integer.class, providerId); + int index = JvmSettings.HANDLENET_INDEX.lookupOptional(Integer.class, providerId).orElse(300); boolean independentHandleService = JvmSettings.HANDLENET_INDEPENDENT_SERVICE .lookupOptional(Boolean.class, providerId).orElse(false); String handleAuthHandle = JvmSettings.HANDLENET_AUTH_HANDLE.lookup(providerId); From 66d2b53dee8afda7cb63764c6acd30bdeed46859 Mon Sep 17 00:00:00 2001 From: qqmye Date: Mon, 4 Mar 2024 15:38:15 -0600 Subject: [PATCH 106/113] add valid fake pid setup for docker --- docker/compose/demo/compose.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker/compose/demo/compose.yml b/docker/compose/demo/compose.yml index a262f43006a..f5203b933f2 100644 --- a/docker/compose/demo/compose.yml +++ b/docker/compose/demo/compose.yml @@ -18,6 +18,11 @@ services: -Ddataverse.files.file1.type=file -Ddataverse.files.file1.label=Filesystem -Ddataverse.files.file1.directory=${STORAGE_DIR}/store + -Ddataverse..pid.providers=fake + -Ddataverse.pid.fake.type=FAKE + -Ddataverse.pid.fake.label=FakeDOIProvider + -Ddataverse.pid.fake.authority=10.5072 + -Ddataverse.pid.fake.shoulder=FK2/ ports: - "8080:8080" # HTTP (Dataverse Application) - "4848:4848" # HTTP (Payara Admin Console) From f6b76a1972baf09b263a99cfe9d31b8580e304e7 Mon Sep 17 00:00:00 2001 From: qqmye Date: Mon, 4 Mar 2024 16:34:52 -0600 Subject: [PATCH 107/113] also adding pid config to the -dev yml --- docker-compose-dev.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 6eab84092ed..f4ed855f19e 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -46,6 +46,11 @@ services: -Ddataverse.files.minio1.download-redirect=false -Ddataverse.files.minio1.access-key=4cc355_k3y -Ddataverse.files.minio1.secret-key=s3cr3t_4cc355_k3y + -Ddataverse..pid.providers=fake + -Ddataverse.pid.fake.type=FAKE + -Ddataverse.pid.fake.label=FakeDOIProvider + -Ddataverse.pid.fake.authority=10.5072 + -Ddataverse.pid.fake.shoulder=FK2/ ports: - "8080:8080" # HTTP (Dataverse Application) - "4848:4848" # HTTP (Payara Admin Console) From aaa81bde27b497a6ac68612cec1a3c5321ef8542 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 5 Mar 2024 09:26:44 -0600 Subject: [PATCH 108/113] Update docker-compose-dev.yml Co-authored-by: Steven Winship <39765413+stevenwinship@users.noreply.github.com> --- docker-compose-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index f4ed855f19e..cdba2e60475 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -46,7 +46,7 @@ services: -Ddataverse.files.minio1.download-redirect=false -Ddataverse.files.minio1.access-key=4cc355_k3y -Ddataverse.files.minio1.secret-key=s3cr3t_4cc355_k3y - -Ddataverse..pid.providers=fake + -Ddataverse.pid.providers=fake -Ddataverse.pid.fake.type=FAKE -Ddataverse.pid.fake.label=FakeDOIProvider -Ddataverse.pid.fake.authority=10.5072 From af40645641b34a9063a9d73c9185f462341cddad Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 5 Mar 2024 09:26:55 -0600 Subject: [PATCH 109/113] Update docker/compose/demo/compose.yml Co-authored-by: Steven Winship <39765413+stevenwinship@users.noreply.github.com> --- docker/compose/demo/compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/compose/demo/compose.yml b/docker/compose/demo/compose.yml index f5203b933f2..85b5e16d91c 100644 --- a/docker/compose/demo/compose.yml +++ b/docker/compose/demo/compose.yml @@ -18,7 +18,7 @@ services: -Ddataverse.files.file1.type=file -Ddataverse.files.file1.label=Filesystem -Ddataverse.files.file1.directory=${STORAGE_DIR}/store - -Ddataverse..pid.providers=fake + -Ddataverse.pid.providers=fake -Ddataverse.pid.fake.type=FAKE -Ddataverse.pid.fake.label=FakeDOIProvider -Ddataverse.pid.fake.authority=10.5072 From 08eb342b7a7e600ef87cc839d9c03975c586ea9f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 5 Mar 2024 22:16:50 -0600 Subject: [PATCH 110/113] Update docker-compose-dev.yml Co-authored-by: Steven Winship <39765413+stevenwinship@users.noreply.github.com> --- docker-compose-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index cdba2e60475..f9534a95c72 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -47,6 +47,7 @@ services: -Ddataverse.files.minio1.access-key=4cc355_k3y -Ddataverse.files.minio1.secret-key=s3cr3t_4cc355_k3y -Ddataverse.pid.providers=fake + -Ddataverse.pid.default-provider=fake -Ddataverse.pid.fake.type=FAKE -Ddataverse.pid.fake.label=FakeDOIProvider -Ddataverse.pid.fake.authority=10.5072 From a4572dbb148c63dc1229cc57f3f8215e929147e2 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 5 Mar 2024 22:17:03 -0600 Subject: [PATCH 111/113] Update docker/compose/demo/compose.yml Co-authored-by: Steven Winship <39765413+stevenwinship@users.noreply.github.com> --- docker/compose/demo/compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/compose/demo/compose.yml b/docker/compose/demo/compose.yml index 85b5e16d91c..e4bcc9778d7 100644 --- a/docker/compose/demo/compose.yml +++ b/docker/compose/demo/compose.yml @@ -19,6 +19,7 @@ services: -Ddataverse.files.file1.label=Filesystem -Ddataverse.files.file1.directory=${STORAGE_DIR}/store -Ddataverse.pid.providers=fake + -Ddataverse.pid.default-provider=fake -Ddataverse.pid.fake.type=FAKE -Ddataverse.pid.fake.label=FakeDOIProvider -Ddataverse.pid.fake.authority=10.5072 From b994d5a93a45ffbea68d134d4edc477f47071551 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 12 Mar 2024 15:09:46 -0400 Subject: [PATCH 112/113] don't return - check legacy settings --- .../iq/dataverse/pidproviders/PidProviderFactoryBean.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java index 7d6e5f57ea9..40044408c63 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProviderFactoryBean.java @@ -123,7 +123,6 @@ private void loadProviders() { if (!providers.isPresent()) { logger.warning( "No PidProviders configured via dataverse.pid.providers. Please consider updating as older PIDProvider configuration mechanisms will be removed in a future version of Dataverse."); - return; } else { for (String id : providers.get()) { //Allows spaces in PID_PROVIDERS setting From 68cd1f112ea49ad69a764e4d7a4815522ef6afd4 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 12 Mar 2024 15:10:04 -0400 Subject: [PATCH 113/113] remove duplicate flyway script --- .../db/migration/V6.1.0.4__3623-multiple-pid-providers.sql | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql diff --git a/src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql b/src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql deleted file mode 100644 index 1d11e178abf..00000000000 --- a/src/main/resources/db/migration/V6.1.0.4__3623-multiple-pid-providers.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE dataverse ADD COLUMN IF NOT EXISTS pidgeneratorspecs TEXT; -ALTER TABLE dataset ADD COLUMN IF NOT EXISTS pidgeneratorspecs TEXT;