DS-2490: Add versioned DOIs and adapt DOI support to service API

This commit is contained in:
Pascal-Nicolas Becker
2015-03-05 12:15:14 +01:00
parent 61ac9371b2
commit 3ae8dfcc4f
8 changed files with 501 additions and 55 deletions

View File

@@ -20,6 +20,7 @@ import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.identifier.doi.DOIConnector;
import org.dspace.identifier.doi.DOIIdentifierException;
@@ -63,6 +64,7 @@ public class DOIIdentifierProvider
static final String CFG_PREFIX = "identifier.doi.prefix";
static final String CFG_NAMESPACE_SEPARATOR = "identifier.doi.namespaceseparator";
static final char SLASH = '/';
// Metadata field name elements
// TODO: move these to MetadataSchema or some such?
@@ -83,11 +85,11 @@ public class DOIIdentifierProvider
@Autowired(required = true)
protected DOIService doiService;
@Autowired(required = true)
protected ItemService itemService;
@Autowired(required = true)
protected ContentServiceFactory contentServiceFactory;
@Autowired(required = true)
protected ItemService itemService;
private DOIIdentifierProvider() {
protected DOIIdentifierProvider() {
}
/**
@@ -165,10 +167,7 @@ public class DOIIdentifierProvider
{
try {
doiService.formatIdentifier(identifier);
} catch (IdentifierException e) {
return false;
} catch (IllegalArgumentException e)
{
} catch (IdentifierException | IllegalArgumentException ex) {
return false;
}
return true;
@@ -182,7 +181,7 @@ public class DOIIdentifierProvider
String doi = mint(context, dso);
// register tries to reserve doi if it's not already.
// So we don't have to reserve it here.
this.register(context, dso, doi);
register(context, dso, doi);
return doi;
}
@@ -347,9 +346,7 @@ public class DOIIdentifierProvider
throws IdentifierException, IllegalArgumentException, SQLException
{
String doi = doiService.formatIdentifier(identifier);
DOI doiRow = null;
doiRow = loadOrCreateDOI(context, dso, doi);
DOI doiRow = loadOrCreateDOI(context, dso, doi);
if (DELETED.equals(doiRow.getStatus()) ||
TO_BE_DELETED.equals(doiRow.getStatus()))
@@ -768,68 +765,97 @@ public class DOIIdentifierProvider
*
* @param context
* @param dso The DSpaceObject the DOI should be loaded or created for.
* @param doi A DOI or null if a DOI should be generated. The generated DOI
* @param doiIdentifier A DOI or null if a DOI should be generated. The generated DOI
* can be found in the appropriate column for the TableRow.
* @return The database row of the object.
* @throws SQLException In case of an error using the database.
* @throws DOIIdentifierException If {@code doi} is not part of our prefix or
* DOI is registered for another object already.
*/
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doi)
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier)
throws SQLException, DOIIdentifierException
{
DOI doiRow = null;
if (null != doi)
DOI doi = null;
if (null != doiIdentifier)
{
// we expect DOIs to have the DOI-Scheme except inside the doi table:
doi = doi.substring(DOI.SCHEME.length());
doiIdentifier = doiIdentifier.substring(DOI.SCHEME.length());
// check if DOI is already in Database
doiRow = doiService.findByDoi(context, doi);
if (null != doiRow)
doi = doiService.findByDoi(context, doiIdentifier);
if (null != doi)
{
// check if DOI already belongs to dso
if (ObjectUtils.equals(doiRow.getDSpaceObject(), dso))
if (doi.getDSpaceObject() == null)
{
return doiRow;
}
else
{
throw new DOIIdentifierException("Trying to create a DOI " +
"that is already reserved for another object.",
DOIIdentifierException.DOI_ALREADY_EXISTS);
// doi was deleted, check resource type
if (doi.getResourceTypeId() != null
&& doi.getResourceTypeId() != dso.getType())
{
// doi was assigend to another resource type. Don't
// reactivate it
throw new DOIIdentifierException("Cannot reassing "
+ "previously deleted DOI " + doiIdentifier
+ " as the resource types of the object it was "
+ "previously assigned to and the object it "
+ "shall be assigned to now divert (was: "
+ Constants.typeText[doi.getResourceTypeId()]
+ ", trying to assign to "
+ Constants.typeText[dso.getType()] + ").",
DOIIdentifierException.DOI_IS_DELETED);
} else {
// reassign doi
// nothing to do here, doi will br reassigned after this
// if-else-if-else-...-block
}
} else {
// doi is assigned to a DSO; is it assigned to our specific dso?
// check if DOI already belongs to dso
if (dso.getID().equals(doi.getDSpaceObject().getID()))
{
return doi;
}
else
{
throw new DOIIdentifierException("Trying to create a DOI " +
"that is already reserved for another object.",
DOIIdentifierException.DOI_ALREADY_EXISTS);
}
}
}
// check prefix
if (!doi.startsWith(this.getPrefix() + "/"))
if (!doiIdentifier.startsWith(this.getPrefix() + "/"))
{
throw new DOIIdentifierException("Trying to create a DOI " +
"that's not part of our Namespace!",
DOIIdentifierException.FOREIGN_DOI);
}
// prepare new doiRow
doiRow = doiService.create(context);
if (doi == null)
{
// prepare new doiRow
doi = doiService.create(context);
}
}
else
{
// We need to generate a new DOI.
doiRow = doiService.create(context);
doi = this.getPrefix() + "/" + this.getNamespaceSeparator() +
doiRow.getId();
doi = doiService.create(context);
doiIdentifier = this.getPrefix() + "/" + this.getNamespaceSeparator() +
doi.getId();
}
doiRow.setDoi(doi);
doiRow.setDSpaceObject(dso);
doiRow.setStatus(null);
// prepare new doiRow
doi.setDoi(doiIdentifier);
doi.setDSpaceObject(dso);
doi.setResourceTypeId(dso.getType());
doi.setStatus(null);
try {
doiService.update(context, doiRow);
doiService.update(context, doi);
} catch (SQLException e) {
throw new RuntimeException("Cannot save DOI to databse for unkown reason.");
}
return doiRow;
return doi;
}
/**
@@ -850,7 +876,7 @@ public class DOIIdentifierProvider
List<MetadataValue> metadata = itemService.getMetadata(item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null);
for (MetadataValue id : metadata)
{
if (id.getValue().startsWith(DOI.RESOLVER + "/10.")) {
if (id.getValue().startsWith(DOI.RESOLVER + String.valueOf(SLASH) + PREFIX + String.valueOf(SLASH) + NAMESPACE_SEPARATOR)) {
return doiService.DOIFromExternalFormat(id.getValue());
}
}
@@ -922,12 +948,6 @@ public class DOIIdentifierProvider
itemService.clearMetadata(context, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null);
itemService.addMetadata(context, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null,
remainder);
try {
itemService.update(context, item);
} catch (SQLException e) {
throw e;
} catch (AuthorizeException e) {
throw e;
}
itemService.update(context, item);
}
}