forked from DSpace/DSpace
-
Notifications
You must be signed in to change notification settings - Fork 22
Issue #1181 doi configuration per community #1370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kuchtiak-ufal
wants to merge
18
commits into
clarin-v7
Choose a base branch
from
issue_#1181_doi_configuration_per_community
base: clarin-v7
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
a65fc06
Issue 1181: enable to set doi prefix and credentials per community
kuchtiak-ufal 04f0d34
update implementation of ClarinDOIIdentifierProvider
kuchtiak-ufal b12db6e
sample configuration of ClarinDOIIdentifierProvider
kuchtiak-ufal 6bd2ed6
extend implementation
kuchtiak-ufal c723d7f
caching identifier providers
kuchtiak-ufal ab4e5cf
Integration test
kuchtiak-ufal 7ad1693
improve test
kuchtiak-ufal 29c49d5
improving implementation - refactoring
kuchtiak-ufal bd5a7d5
documentation improvement
kuchtiak-ufal 1648a9c
resolve Copilot comments
kuchtiak-ufal 732e053
improve init() method in ClarinCommunityDOIIdentifierProvider
kuchtiak-ufal 2f3234a
fixed schemaLocation in DIM2DataCite.xsl
kuchtiak-ufal a001cfb
change caching: cache only to null when item is in non configurable c…
kuchtiak-ufal bbd324f
fixed invalid DIM2DataCite.xsl file
kuchtiak-ufal 51a4ae8
Merge branch 'clarin-v7' into issue_#1181_doi_configuration_per_commu…
kuchtiak-ufal a7fe6fa
resolve MR comment - don't derive doi from item versions
kuchtiak-ufal e17bb31
update sample DOI per Community configuration
kuchtiak-ufal de3af45
fixed failing Integration tests
kuchtiak-ufal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
177 changes: 177 additions & 0 deletions
177
dspace-api/src/main/java/org/dspace/identifier/ClarinCommunityDOIIdentifierProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| /** | ||
| * The contents of this file are subject to the license and copyright | ||
| * detailed in the LICENSE and NOTICE files at the root of the source | ||
| * tree and available online at | ||
| * | ||
| * http://www.dspace.org/license/ | ||
| */ | ||
| package org.dspace.identifier; | ||
|
|
||
| import java.sql.SQLException; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
| import org.dspace.authorize.AuthorizeException; | ||
| import org.dspace.content.DSpaceObject; | ||
| import org.dspace.content.Item; | ||
| import org.dspace.content.MetadataValue; | ||
| import org.dspace.content.logic.Filter; | ||
| import org.dspace.core.Context; | ||
| import org.dspace.identifier.doi.ClarinDataCiteConnector; | ||
| import org.dspace.identifier.doi.DOIConnector; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
|
|
||
| /** | ||
| * DOI identifier provider for CLARIN communities. | ||
| * It uses the ClarinDataCiteConnector to connect to DataCite and requires the DOI prefix | ||
| * and the list of CLARIN community IDs to be configured. | ||
| * | ||
| * @author Milan Kuchtiak (kuchtiak@ufal.mff.cuni.cz) | ||
| */ | ||
| public class ClarinCommunityDOIIdentifierProvider extends DOIIdentifierProvider { | ||
|
|
||
| private static final Logger log = LogManager.getLogger(ClarinCommunityDOIIdentifierProvider.class); | ||
|
|
||
| protected DOIConnector connector; | ||
|
|
||
| private String doiPrefix; | ||
|
|
||
| private String namespaceSeparator; | ||
|
|
||
| private Set<String> communities = new HashSet<>(); | ||
|
|
||
| public void init() { | ||
| if (!(this.connector instanceof ClarinDataCiteConnector)) { | ||
| throw new IllegalStateException("ClarinCommunityDOIIdentifierProvider requires ClarinDataCiteConnector"); | ||
| } | ||
| if (doiPrefix == null) { | ||
| throw new IllegalStateException("No DOI prefix configured for ClarinCommunityDOIIdentifierProvider"); | ||
| } | ||
| if (namespaceSeparator == null) { | ||
| namespaceSeparator = ""; | ||
| } | ||
|
|
||
| ClarinDataCiteConnector dataCiteConnector = (ClarinDataCiteConnector) this.connector; | ||
|
|
||
| dataCiteConnector.setDoiPrefix(doiPrefix); | ||
|
|
||
|
kuchtiak-ufal marked this conversation as resolved.
|
||
| String username = this.configurationService.getProperty("identifier.doi." + doiPrefix + ".user"); | ||
| if (username == null) { | ||
| log.error("No username configured for DOI prefix '{}'", doiPrefix); | ||
| throw new IllegalStateException("No username configured for DOI prefix '" + doiPrefix + "'"); | ||
| } | ||
| dataCiteConnector.setUsername(username); | ||
|
|
||
| String password = this.configurationService.getProperty("identifier.doi." + doiPrefix + ".password"); | ||
| if (password == null) { | ||
| log.error("No password configured for DOI prefix '{}'", doiPrefix); | ||
| throw new IllegalStateException("No password configured for DOI prefix '" + doiPrefix + "'"); | ||
| } | ||
| dataCiteConnector.setPassword(password); | ||
| } | ||
|
|
||
| @Override | ||
| @Autowired(required = true) | ||
| public void setDOIConnector(DOIConnector connector) { | ||
| super.setDOIConnector(connector); | ||
| this.connector = connector; | ||
| } | ||
|
|
||
| /** | ||
| * Mint a new DOI identifier for a given DSpaceObject. This method cleans up any old DOI metadata | ||
| * that may be left on the item if it was versioned and the DOI metadata was | ||
| * not removed from the original item before versioning. | ||
| * | ||
| * @param context - DSpace context | ||
| * @param dso - DSpaceObject identified by the new identifier | ||
| * @param filter - Logical item filter to determine whether this identifier should be registered | ||
| * @return minted DOI identifier for the given DSpaceObject | ||
| */ | ||
| @Override | ||
| public String mint(Context context, DSpaceObject dso, Filter filter) throws IdentifierException { | ||
| if (!(dso instanceof Item)) { | ||
| throw new IdentifierException("Currently only Items are supported for DOIs."); | ||
| } | ||
| Item item = (Item) dso; | ||
|
|
||
| try { | ||
| String doi = getDOIByObject(context, dso); | ||
| if (doi != null) { | ||
| return doi; | ||
| } | ||
| } catch (SQLException e) { | ||
| log.error("Error while attempting to retrieve information about a DOI for " | ||
| + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + | ||
| " with ID " + dso.getID() + "."); | ||
| throw new RuntimeException("Error while attempting to retrieve " + | ||
| "information about a DOI for " + | ||
| contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + | ||
| " with ID " + dso.getID() + ".", e); | ||
| } | ||
| String doi; | ||
| try { | ||
| doi = loadOrCreateDOI(context, dso, null, filter).getDoi(); | ||
| } catch (SQLException e) { | ||
| log.error("Error while creating new DOI for Object of " + | ||
| "ResourceType {} with id {}.", dso.getType(), dso.getID()); | ||
| throw new RuntimeException("Error while attempting to create a " + | ||
| "new DOI for " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + | ||
| " with ID " + dso.getID() + ".", e); | ||
| } | ||
|
|
||
| // check whether we have old DOI metadata and if we have - remove it | ||
| // this metadata could be left on the item if it was versioned | ||
| // and the DOI metadata was not removed from the original item before versioning | ||
| String leftPart = doiService.getResolver() + SLASH + getPrefix() + SLASH + getNamespaceSeparator(); | ||
| List<MetadataValue> metadataToRemove = | ||
| itemService.getMetadata(item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, Item.ANY) | ||
| .stream() | ||
| .filter(id -> id.getValue().startsWith(leftPart)) | ||
| .collect(Collectors.toList()); | ||
| if (!metadataToRemove.isEmpty()) { | ||
| log.debug("Found old DOI metadata that needs to be removed."); | ||
| try { | ||
| itemService.removeMetadataValues(context, item, metadataToRemove); | ||
| itemService.update(context, item); | ||
| } catch (SQLException e) { | ||
| throw new RuntimeException(e); | ||
| } catch (AuthorizeException e) { | ||
| throw new RuntimeException( | ||
| "Trying to remove an old DOI from a versioned item, but wasn't authorized to.", e); | ||
| } | ||
| } | ||
|
|
||
| return doi.startsWith(DOI.SCHEME) ? doi : DOI.SCHEME + doi; | ||
| } | ||
|
|
||
| public void setDoiPrefix(String doiPrefix) { | ||
| this.doiPrefix = doiPrefix; | ||
| } | ||
|
|
||
| public void setNamespaceSeparator(String namespaceSeparator) { | ||
| this.namespaceSeparator = namespaceSeparator; | ||
| } | ||
|
|
||
| public void setCommunities(Set<String> communities) { | ||
| this.communities = communities; | ||
| } | ||
|
|
||
| @Override | ||
| protected String getPrefix() { | ||
| return this.doiPrefix; | ||
| } | ||
|
|
||
| @Override | ||
| protected String getNamespaceSeparator() { | ||
| return this.namespaceSeparator; | ||
| } | ||
|
|
||
| Set<String> getCommunities() { | ||
| return this.communities; | ||
| } | ||
|
|
||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushing username/password/prefix onto the connector at
init()is safe with the example wiring only because each provider gets its own inner-bean connector. If someone later rewires the connector as a sharedref, all providers silently collapse onto the last-initialized credentials/prefix — DOIs minted against the wrong DataCite account, no error.Since
ClarinDataCiteConnectoralready has the setters, consider configuring username/password/prefix directly on each connector bean in Spring and dropping this push (and theidentifier.doi.<prefix>.user/.passwordindirection) entirely. Smaller class, no hidden coupling.