mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-19 07:53:08 +00:00
Simpliefied code of DOIIdentifierProvider. Enhanced Exception handling.
This commit is contained in:
@@ -18,6 +18,7 @@ import org.dspace.content.FormatIdentifier;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.identifier.doi.DOIConnector;
|
||||
import org.dspace.identifier.doi.DOIIdentifierException;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.slf4j.Logger;
|
||||
@@ -41,6 +42,20 @@ public class DOIIdentifierProvider
|
||||
extends IdentifierProvider
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(DOIIdentifierProvider.class);
|
||||
|
||||
/**
|
||||
* A DOIConnector connects the DOIIdentifierProvider to the API of the DOI
|
||||
* registration agency needed to register DOIs. To register DOIs we have to
|
||||
* care about two APIs: the <link>IdentifierProvider</link> API of DSpace
|
||||
* and the API of the DOI registration agency. The DOIIdentifierProvider
|
||||
* manages the DOI database table, generates new DOIs, stores them as
|
||||
* metadata in DSpace items and so on. To register DOIs at DOI registration
|
||||
* agencies it uses a DOIConnector. A DOI connector has to register and
|
||||
* reserve DOIs using the API of the DOI registration agency. If requested
|
||||
* by the registration agency it has to convert and send metadata of the
|
||||
* DSpace items.
|
||||
*/
|
||||
private DOIConnector connector;
|
||||
|
||||
static final String CFG_PREFIX = "identifier.doi.prefix";
|
||||
static final String CFG_NAMESPACE_SEPARATOR = "identifier.doi.namespaceseparator";
|
||||
@@ -51,9 +66,6 @@ public class DOIIdentifierProvider
|
||||
public static final String DOI_ELEMENT = "identifier";
|
||||
public static final String DOI_QUALIFIER = null;
|
||||
|
||||
// How many times do we want to try to find a new unique DOI?
|
||||
private static final int THRESHOLD_UNIQUE_DOI = 1000;
|
||||
|
||||
/**
|
||||
* Prefix of DOI namespace. Set in dspace.cfg.
|
||||
*/
|
||||
@@ -61,7 +73,7 @@ public class DOIIdentifierProvider
|
||||
|
||||
/**
|
||||
* Part of DOI to separate several applications that generate DOIs.
|
||||
* E.g. it could be 'dspace/' if DOIs generated by DSpace should have the form
|
||||
* E.g. it could be 'dspace/' if DOIs generated by DSpace should have the form
|
||||
* prefix/dspace/uniqueString. Set it to the empty String if DSpace must
|
||||
* generate DOIs directly after the DOI Prefix. Set in dspace.cfg.
|
||||
*/
|
||||
@@ -96,9 +108,6 @@ public class DOIIdentifierProvider
|
||||
return this.NAMESPACE_SEPARATOR;
|
||||
}
|
||||
|
||||
|
||||
private DOIConnector connector;
|
||||
|
||||
@Required
|
||||
public void setDOIConnector(DOIConnector connector)
|
||||
{
|
||||
@@ -132,10 +141,10 @@ public class DOIIdentifierProvider
|
||||
{
|
||||
try {
|
||||
DOI.formatIdentifier(identifier);
|
||||
} catch (IdentifierException e) {
|
||||
} catch (IdentifierException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -155,56 +164,35 @@ public class DOIIdentifierProvider
|
||||
throws IdentifierException
|
||||
{
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
|
||||
TableRow doiRow = null;
|
||||
|
||||
String status;
|
||||
|
||||
if (null != doi) {
|
||||
try {
|
||||
// get DOI object from Database
|
||||
// remove DOI.SCHEME before searching in DB.
|
||||
doiRow = DatabaseManager.findByUnique(context, "Doi",
|
||||
"doi", doi.substring(DOI.SCHEME.length()));
|
||||
|
||||
|
||||
if (null == doiRow) {
|
||||
try {
|
||||
createNewIdentifier(context, dso, doi);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO: better exception handling
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
log.warn("Trying to register DOI {}, that not exist in DB.", doi);
|
||||
|
||||
} else {
|
||||
|
||||
if (doiRow.getIntColumn("resource_id") != dso.getID()
|
||||
|| doiRow.getIntColumn("resource_type_id") != dso.getType()) {
|
||||
|
||||
throw new IdentifierException("Trying to reserve a DOI "
|
||||
+ "that is reserved for another object.");
|
||||
}
|
||||
|
||||
if ("isRegistered".equals(doiRow.getStringColumn("status")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
doiRow.setColumn("status", "toBeRegistered");
|
||||
DatabaseManager.update(context, doiRow);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
log.error("Error while trying to change doi status "
|
||||
+ dso.getTypeText() + " with ID " + dso.getID() + ".");
|
||||
throw new RuntimeException("Error while while trying to change doi status "
|
||||
+ "for a DOI " + dso.getTypeText()
|
||||
+ " with ID " + dso.getID() + ".", ex);
|
||||
}
|
||||
// search DOI in our db
|
||||
try
|
||||
{
|
||||
doiRow = loadOrCreateDOI(context, dso, doi);
|
||||
} catch (SQLException ex) {
|
||||
log.error("Error in databse connection: " + ex.getMessage());
|
||||
throw new RuntimeException("Error in database conncetion.", ex);
|
||||
}
|
||||
|
||||
// Check status of DOI
|
||||
if ("isRegistered".equals(doiRow.getStringColumn("status")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// change status of DOI
|
||||
doiRow.setColumn("status", "toBeRegistered");
|
||||
try {
|
||||
DatabaseManager.update(context, doiRow);
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
log.warn("SQLException while changing status of DOI {} to be registered.", doi);
|
||||
throw new RuntimeException(sqle);
|
||||
}
|
||||
|
||||
// safe DOI as metadata of the item
|
||||
try {
|
||||
saveDOIToObject(context, dso, doi);
|
||||
}
|
||||
@@ -212,9 +200,9 @@ public class DOIIdentifierProvider
|
||||
{
|
||||
throw new IdentifierException("Not authorized to save a DOI as metadata of an dso!", ae);
|
||||
}
|
||||
catch (SQLException e)
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
throw new RuntimeException(sqle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,158 +224,145 @@ public class DOIIdentifierProvider
|
||||
@Override
|
||||
public void reserve(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException, IllegalArgumentException
|
||||
{
|
||||
this.reserveDOI(context, dso, identifier);
|
||||
}
|
||||
|
||||
private void reserveDOI(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException, IllegalArgumentException
|
||||
{
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
|
||||
TableRow doiRow = null;
|
||||
|
||||
|
||||
// ensure that the DOI is in our DOI table and is not reserved online
|
||||
// for another object than dso
|
||||
try {
|
||||
createNewIdentifier(context, dso, doi);
|
||||
|
||||
doiRow = DatabaseManager.findByUnique(context, "Doi",
|
||||
"doi", doi.substring(DOI.SCHEME.length()));
|
||||
|
||||
if (null == doiRow) {
|
||||
log.warn("Trying to reserve DOI {}, that not exist in DB.", doi);
|
||||
throw new IdentifierException("Trying to reserve a DOI "
|
||||
+ "that not exist in DB.");
|
||||
} else {
|
||||
|
||||
if (doiRow.getIntColumn("resource_id") != dso.getID()
|
||||
|| doiRow.getIntColumn("resource_type_id") != dso.getType()) {
|
||||
|
||||
throw new IdentifierException("Trying to reserve a DOI "
|
||||
+ "that is reserved for another object.");
|
||||
}
|
||||
|
||||
if (!doiRow.isColumnNull("status")) {
|
||||
return;
|
||||
}
|
||||
|
||||
doiRow.setColumn("status", "toBeReserved");
|
||||
DatabaseManager.update(context, doiRow);
|
||||
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IdentifierException("DOI is reserved for another object.");
|
||||
} catch (SQLException ex) {
|
||||
throw new RuntimeException("Error in database connection: " + ex.getMessage());
|
||||
// if the doi is in our db already loadOrCreateDOI just returns.
|
||||
// if it is not loadOrCreateDOI safes the doi.
|
||||
doiRow = loadOrCreateDOI(context, dso, doi);
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
throw new RuntimeException(sqle);
|
||||
}
|
||||
|
||||
if (!doiRow.isColumnNull("status")) {
|
||||
return;
|
||||
}
|
||||
|
||||
doiRow.setColumn("status", "toBeReserved");
|
||||
try
|
||||
{
|
||||
DatabaseManager.update(context, doiRow);
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
throw new RuntimeException(sqle);
|
||||
}
|
||||
}
|
||||
|
||||
public void reserveDOIOnline(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||
|
||||
public void reserveOnline(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException, IllegalArgumentException, SQLException
|
||||
{
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
// ensure that the DOI is in our DOI table and is not reserved online
|
||||
// for another object than dso
|
||||
try {
|
||||
createNewIdentifier(context, dso, doi);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IdentifierException("DOI is reserved for another object.");
|
||||
} catch (SQLException ex) {
|
||||
throw new RuntimeException("Error in database connection: " + ex.getMessage());
|
||||
}
|
||||
|
||||
// check if DOI is reserved at the registration agency for the specific dso
|
||||
if (connector.isDOIReserved(context, dso, doi)) {
|
||||
// TODO: Send metadata update anyway!
|
||||
return;
|
||||
}
|
||||
|
||||
// check if doi is already reserved for another object
|
||||
if (connector.isDOIReserved(context, doi)) {
|
||||
log.warn("Trying to reserve a DOI {} that is reserved for "
|
||||
+ "another object.", doi);
|
||||
throw new IdentifierException("Trying to reserve a DOI "
|
||||
+ "that is reserved for another object.");
|
||||
}
|
||||
// get TableRow and ensure DOI belongs to dso regarding our db
|
||||
TableRow doiRow = loadOrCreateDOI(context, dso, doi);
|
||||
|
||||
// try to reserve the doi
|
||||
if (!connector.reserveDOI(context, dso, doi)) {
|
||||
throw new IdentifierException("It was impossible to reserve the DOI "
|
||||
+ doi + ". Take a look into the logs for further details.");
|
||||
// check if DOI is reserved at the registration agency
|
||||
if (connector.isDOIReserved(context, doi))
|
||||
{
|
||||
// if doi is registered for this object we still should check its
|
||||
// status in our database (see below).
|
||||
// if it is registered for another object we should notify an admin
|
||||
if (!connector.isDOIReserved(context, dso, doi))
|
||||
{
|
||||
log.warn("DOI {} is reserved for another object already.", doi);
|
||||
throw new DOIIdentifierException(DOIIdentifierException.DOI_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TableRow doiRow = DatabaseManager.findByUnique(context, "Doi",
|
||||
"doi", doi.substring(DOI.SCHEME.length()));
|
||||
doiRow.setColumn("status", "isReserved");
|
||||
try {
|
||||
DatabaseManager.update(context, doiRow);
|
||||
} catch (SQLException se) { ///muss ich sehenn
|
||||
System.err.println("Caught SQLException: " + se.getMessage());
|
||||
se.printStackTrace(System.err);
|
||||
throw se;
|
||||
}
|
||||
connector.reserveDOI(context, dso, doi);
|
||||
}
|
||||
|
||||
doiRow.setColumn("status", "isReserved");
|
||||
DatabaseManager.update(context, doiRow);
|
||||
}
|
||||
|
||||
public void registeredDOIOnline(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||
public void registereOnline(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException, IllegalArgumentException, SQLException
|
||||
{
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
// check if the DOI is already registered for this dso
|
||||
if (connector.isDOIRegistered(context, dso, doi))
|
||||
// get TableRow and ensure DOI belongs to dso regarding our db
|
||||
TableRow doiRow = loadOrCreateDOI(context, dso, doi);
|
||||
|
||||
// check if the DOI is already registered online
|
||||
if (connector.isDOIRegistered(context, doi))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// check if DOI is registered for another object
|
||||
if (connector.isDOIRegistered(context, doi)) {
|
||||
log.warn("Trying to register DOI {}, that is already registered.", doi);
|
||||
throw new IdentifierException("Trying to register a DOI that is "
|
||||
+ "registered for another object.");
|
||||
}
|
||||
|
||||
// check if doi is reserved for this specific dso
|
||||
if (!connector.isDOIReserved(context, dso, doi)) {
|
||||
// check if doi is already reserved for another dso
|
||||
if (connector.isDOIReserved(context, doi)) {
|
||||
log.warn("Trying to register DOI {}, that is reserved for "
|
||||
+ "another dso.", doi);
|
||||
throw new IdentifierException("Trying to register a DOI "
|
||||
+ "that is reserved for another object.");
|
||||
// if doi is registered for this object we still should check its
|
||||
// status in our database (see below).
|
||||
// if it is registered for another object we should notify an admin
|
||||
if (!connector.isDOIRegistered(context, dso, doi))
|
||||
{
|
||||
// DOI is reserved for another object
|
||||
log.warn("DOI {} is registered for another object already.", doi);
|
||||
throw new DOIIdentifierException(DOIIdentifierException.DOI_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if (!connector.reserveDOI(context, dso, doi)) {
|
||||
throw new IdentifierException("It was impossible to reserve the DOI "
|
||||
+ doi + ". Take a look into the logs for further details.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// register DOI Online
|
||||
try {
|
||||
connector.registerDOI(context, dso, doi);
|
||||
}
|
||||
catch (DOIIdentifierException die)
|
||||
{
|
||||
// do we have to reserve DOI before we can register it?
|
||||
if (die.getCode() == DOIIdentifierException.REGISTER_FIRST)
|
||||
{
|
||||
this.reserveOnline(context, dso, identifier);
|
||||
connector.registerDOI(context, dso, doi);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw die;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!connector.registerDOI(context, dso, doi)) {
|
||||
throw new IdentifierException("It was impossible to register the DOI "
|
||||
+ doi + ". Take a look into the logs for further details.");
|
||||
} else {
|
||||
TableRow doiRow = DatabaseManager.findByUnique(context, "Doi",
|
||||
"doi", doi.substring(DOI.SCHEME.length()));
|
||||
doiRow.setColumn("status", "isRegistered");
|
||||
DatabaseManager.update(context, doiRow);
|
||||
doiRow.setColumn("status", "isRegistered");
|
||||
DatabaseManager.update(context, doiRow);
|
||||
}
|
||||
|
||||
public void updateMetadata(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException
|
||||
{
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
|
||||
// ensure DOI belongs to dso regarding our db
|
||||
TableRow doiRow = null;
|
||||
try
|
||||
{
|
||||
doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi);
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
log.warn("SQLException while searching a DOI in our db.", sqle);
|
||||
throw new RuntimeException("Unable to retrieve information about "+
|
||||
"a DOI out of database.", sqle);
|
||||
}
|
||||
if (null == doiRow)
|
||||
{
|
||||
log.error("Cannot update metadata for DOI {}: unable to find it in "
|
||||
+ "our db.", doi);
|
||||
throw new DOIIdentifierException("Unable to find DOI.",
|
||||
DOIIdentifierException.DOI_DOES_NOT_EXIST);
|
||||
}
|
||||
if (doiRow.getIntColumn("resource_id") != dso.getID() ||
|
||||
doiRow.getIntColumn("resource_type_id") != dso.getType())
|
||||
{
|
||||
log.error("Refuse to update metadata of DOI {} with the metadata of "
|
||||
+ " an object ({}/{}) the DOI is not dedicated to.",
|
||||
new String[] {doi, dso.getTypeText(), Integer.toString(dso.getID())});
|
||||
throw new DOIIdentifierException("Cannot update DOI metadata: "
|
||||
+ "DOI and DSpaceObject does not match!",
|
||||
DOIIdentifierException.MISMATCH);
|
||||
}
|
||||
|
||||
connector.updateMetadata(context, dso, doi);
|
||||
}
|
||||
|
||||
public void updateMetadata(Context context, DSpaceObject dso, String identifier )
|
||||
throws IdentifierException
|
||||
{
|
||||
|
||||
String doi = formatIdentifier(identifier);
|
||||
if(connector.updateMetadata(context, dso, doi))
|
||||
return;
|
||||
throw new IdentifierException("it wasn't possible to update metadata for "
|
||||
+ "the DOI" + identifier + ". Take a look into the logs"
|
||||
+ " for further details.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mint(Context context, DSpaceObject dso)
|
||||
@@ -410,7 +385,9 @@ public class DOIIdentifierProvider
|
||||
{
|
||||
try
|
||||
{
|
||||
doi = createNewIdentifier(context, dso, null);
|
||||
TableRow doiRow = loadOrCreateDOI(context, dso, null);
|
||||
doi = DOI.SCHEME + doiRow.getStringColumn("doi");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
@@ -432,16 +409,22 @@ public class DOIIdentifierProvider
|
||||
try {
|
||||
doi = DOI.formatIdentifier(identifier);
|
||||
} catch (IdentifierException e) {
|
||||
throw new IdentifierNotResolvableException(e.getMessage());
|
||||
throw new IdentifierNotResolvableException(e);
|
||||
}
|
||||
try
|
||||
{
|
||||
return getObjectByDOI(context, doi);
|
||||
DSpaceObject dso = getObjectByDOI(context, doi);
|
||||
if (null == dso)
|
||||
{
|
||||
throw new IdentifierNotFoundException();
|
||||
}
|
||||
return dso;
|
||||
}
|
||||
catch (SQLException e)
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
log.error("SQLException while searching a DOI in our db.", sqle);
|
||||
throw new RuntimeException("Unable to retrieve information about "+
|
||||
"a DOI out of database.", e);
|
||||
"a DOI out of database.", sqle);
|
||||
}
|
||||
catch (IdentifierException e)
|
||||
{
|
||||
@@ -464,8 +447,10 @@ public class DOIIdentifierProvider
|
||||
}
|
||||
|
||||
if (null == doi)
|
||||
{
|
||||
throw new IdentifierNotFoundException("No DOI for DSpaceObject of type "
|
||||
+ dso.getTypeText() + " with ID " + dso.getID() + " found.");
|
||||
}
|
||||
|
||||
return doi;
|
||||
}
|
||||
@@ -481,8 +466,7 @@ public class DOIIdentifierProvider
|
||||
catch (SQLException e)
|
||||
{
|
||||
log.error("Error while attemping to retrieve information about a DOI for "
|
||||
+ dso.getTypeText() + " with ID " + dso.getID() + ".");
|
||||
log.error(e.getMessage());
|
||||
+ dso.getTypeText() + " with ID " + dso.getID() + ".", e);
|
||||
throw new RuntimeException("Error while attempting to retrieve " +
|
||||
"information about a DOI for " + dso.getTypeText() +
|
||||
" with ID " + dso.getID() + ".", e);
|
||||
@@ -490,7 +474,7 @@ public class DOIIdentifierProvider
|
||||
if (doi == null)
|
||||
{
|
||||
// doi is not in DB. Is it in dso metadata?
|
||||
doi = this.getDOIOutOfObject(dso);
|
||||
doi = getDOIOutOfObject(dso);
|
||||
}
|
||||
if (doi != null)
|
||||
{
|
||||
@@ -502,27 +486,41 @@ public class DOIIdentifierProvider
|
||||
public void delete(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException
|
||||
{
|
||||
deleteDOI(context, dso, identifier);
|
||||
}
|
||||
|
||||
private void deleteDOI(Context context, DSpaceObject dso, String identifier)
|
||||
throws IdentifierException
|
||||
{
|
||||
log.debug("delete {} from {}", identifier, dso);
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
log.debug("formated identifier as {}", doi);
|
||||
TableRow doiRow = null;
|
||||
String oldStatus = null;
|
||||
|
||||
// look for doi in DB
|
||||
// if it exists compare resource type and id
|
||||
// if not okay throw exception
|
||||
try
|
||||
{
|
||||
doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi);
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
throw new RuntimeException(sqle);
|
||||
}
|
||||
|
||||
// check if DOI belongs to dso
|
||||
if (null != doiRow)
|
||||
{
|
||||
if (doiRow.getIntColumn("resource_id") != dso.getID() ||
|
||||
doiRow.getIntColumn("resource_type_id") != dso.getType())
|
||||
{
|
||||
throw new DOIIdentifierException("Trying to delete a DOI out of "
|
||||
+ "an object that is not addressed by the DOI.",
|
||||
DOIIdentifierException.MISMATCH);
|
||||
}
|
||||
}
|
||||
|
||||
// remove DOI from metadata
|
||||
try
|
||||
{
|
||||
removeDOIFromObject(context, dso, doi);
|
||||
}
|
||||
catch (AuthorizeException ex)
|
||||
{
|
||||
log.error("Not authorized to delete a DOI out of an Item.");
|
||||
throw new IdentifierException("Not authorized to delete DOI.", ex);
|
||||
log.error("Not authorized to delete a DOI out of an Item.", ex);
|
||||
throw new DOIIdentifierException("Not authorized to delete DOI.",
|
||||
ex, DOIIdentifierException.UNAUTHORIZED_METADATA_MANIPULATION);
|
||||
}
|
||||
catch (SQLException ex)
|
||||
{
|
||||
@@ -532,64 +530,23 @@ public class DOIIdentifierProvider
|
||||
"metadata of an Item " + dso.getID(), ex);
|
||||
}
|
||||
|
||||
// DOIs are persistent identifier and should not be deleted at all.
|
||||
// DataCite, for example, can mark a DOI as inactive and uses http delete
|
||||
// method to do so.
|
||||
// DOIConnector returns boolean, try to delete DOI:
|
||||
if(!connector.deleteDOI(context, doi))
|
||||
// change doi status in db if necessary.
|
||||
if (null != doiRow)
|
||||
{
|
||||
// It was not possible to delete a DOI at the registry agency. We
|
||||
// already removed the DOI out of the object's metadata,
|
||||
// so we should restore this information.
|
||||
try
|
||||
{
|
||||
saveDOIToObject(context, dso, doi);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
log.error("We were authorized to delete a DOI out of an Item, " +
|
||||
"but we can't restore these informations?!");
|
||||
log.error("DSO-Type: " + dso.getTypeText() + ", ID: " +
|
||||
dso.getID() + ", DOI: " + doi + ".");
|
||||
throw new IllegalStateException("We were authorized to delete " +
|
||||
"a DOI out of an Item, but we can't restore these informations?!", e);
|
||||
}
|
||||
catch (SQLException ex)
|
||||
{
|
||||
log.error("SQLError while restoring DOI " + doi +
|
||||
" for Object of Type " + dso.getTypeText() + " with ID "
|
||||
+ dso.getID() + ".");
|
||||
log.error("Exception message: " + ex.getMessage());
|
||||
throw new RuntimeException("Error while restoring a DOI as " +
|
||||
"metadata of an Item " + dso.getID(), ex);
|
||||
}
|
||||
throw new IdentifierException("Unable to delete DOI " + doi +
|
||||
". Take a look into the logs for further details.");
|
||||
}
|
||||
|
||||
// last thing to do is to delete the relation between DOI and item
|
||||
try{
|
||||
TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi);
|
||||
if (doiRow != null)
|
||||
{
|
||||
// Set ressource_id and type_id to null. In opposition to
|
||||
// HandleIdentifierProvider we don't want to reuse DOIs at all!
|
||||
doiRow.setColumnNull("resource_id");
|
||||
doiRow.setColumnNull("resource_type_id");
|
||||
doiRow.setColumn("status", "deleted");
|
||||
try {
|
||||
DatabaseManager.update(context, doiRow);
|
||||
}
|
||||
else
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
log.warn("Cannot find entry for DOI " + doi +". Wanted to "
|
||||
+ "the doi for object " + dso.getTypeText() + " id="
|
||||
+ dso.getID());
|
||||
log.warn("SQLException while changing status of DOI {} to be registered.", doi);
|
||||
throw new RuntimeException(sqle);
|
||||
}
|
||||
}
|
||||
catch(SQLException sqe)
|
||||
{
|
||||
throw new IdentifierException(sqe.getMessage(),sqe);
|
||||
}
|
||||
log.info("Deleted {}", doi);
|
||||
}
|
||||
|
||||
// DOI is a permanent identifier. DataCite for example does not delete
|
||||
// DOIS. But it is possible to mark a DOI as "inactive".
|
||||
connector.deleteDOI(context, doi);
|
||||
}
|
||||
|
||||
|
||||
@@ -597,24 +554,29 @@ public class DOIIdentifierProvider
|
||||
* Returns a DSpaceObject depending on its DOI.
|
||||
* @param context the context
|
||||
* @param identifier The DOI in a format that is accepted by
|
||||
* {@link DOI.formatIdentifier(String)}.
|
||||
* {@link formatIdentifier(String)}.
|
||||
* @return Null if the DOI couldn't be found or the associated DSpaceObject.
|
||||
* @throws SQLException
|
||||
* @throws IdentifierException If {@code identifier} is null or an empty string.
|
||||
* @throws IllegalArgumentException If the identifier couldn't be recognized as DOI.
|
||||
*/
|
||||
public static DSpaceObject getObjectByDOI(Context context, String identifier)
|
||||
throws SQLException, IdentifierException, IllegalArgumentException
|
||||
throws SQLException, DOIIdentifierException, IllegalArgumentException
|
||||
{
|
||||
String doi = DOI.formatIdentifier(identifier);
|
||||
TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi);
|
||||
TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi",
|
||||
doi.substring(DOI.SCHEME.length()));
|
||||
|
||||
if (null == doiRow)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (doiRow.isColumnNull("resource_type_id") ||
|
||||
doiRow.isColumnNull("resource_id"))
|
||||
{
|
||||
log.error("Found DOI " + doi +
|
||||
" in database, but no assigned Object could be found.");
|
||||
throw new IllegalStateException("Found DOI " + doi +
|
||||
" in database, but no assigned Object could be found.");
|
||||
}
|
||||
@@ -641,7 +603,9 @@ public class DOIIdentifierProvider
|
||||
TableRow doiRow = DatabaseManager.querySingleTable(context,
|
||||
"Doi", sql, dso.getType(), dso.getID());
|
||||
if (null == doiRow)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (doiRow.isColumnNull("doi"))
|
||||
{
|
||||
@@ -656,118 +620,105 @@ public class DOIIdentifierProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DOI and saves it to the database.
|
||||
* Load a DOI from the database or creates it if it does not exist. This
|
||||
* method can be used to ensure that a DOI exists in the database and to
|
||||
* load the appropriate TableRow. As protected method we don't check if the
|
||||
* DOI is in a decent format, use DOI.formatIdentifier(String) if necessary.
|
||||
*
|
||||
* @param context
|
||||
* @param dso The DSpaceObject the DOI should be created for.
|
||||
* @param doi A DOI or null if DOI should be generated.
|
||||
* @return The generated DOI or {@code doi} if it was saved to the database.
|
||||
* @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
|
||||
* 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 IllegalArgumentException If the given DOI already exists for an other object.
|
||||
* @throws IdentifierException If {@code doi} is not part of our prefix or
|
||||
* the doi registry assumes that the DOI belongs
|
||||
* to another party.
|
||||
* @throws DOIIdentifierException If {@code doi} is not part of our prefix or
|
||||
* DOI is registered for another object already.
|
||||
*/
|
||||
protected String createNewIdentifier(Context context, DSpaceObject dso, String doi)
|
||||
throws SQLException, IllegalArgumentException, IdentifierException
|
||||
protected TableRow loadOrCreateDOI(Context context, DSpaceObject dso, String doi)
|
||||
throws SQLException, DOIIdentifierException
|
||||
{
|
||||
TableRow doiRow = null;
|
||||
if (null != doi)
|
||||
{
|
||||
// we expect DOIs to have the DOI-Scheme except inside the doi table:
|
||||
doi = doi.substring(DOI.SCHEME.length());
|
||||
|
||||
// check if DOI is already in Database
|
||||
// remove DOI.SCHEME before searching in DB.
|
||||
doiRow = DatabaseManager.findByUnique(context, "Doi",
|
||||
"doi", doi.substring(DOI.SCHEME.length()));
|
||||
doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi);
|
||||
if (null != doiRow)
|
||||
{
|
||||
// check if DOI already belongs to dso
|
||||
if (doiRow.getIntColumn("resource_id") == dso.getID() &&
|
||||
doiRow.getIntColumn("resource_type_id") == dso.getType())
|
||||
{
|
||||
return doi;
|
||||
return doiRow;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Trying to save a DOI " +
|
||||
"that is already reserved for another object.");
|
||||
throw new DOIIdentifierException("Trying to create a DOI " +
|
||||
"that is already reserved for another object.",
|
||||
DOIIdentifierException.DOI_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// doi is not null but was not found in db
|
||||
// check if it is reserved online for another object
|
||||
if (!connector.isDOIReserved(context, dso, doi) &&
|
||||
connector.isDOIReserved(context, doi))
|
||||
{
|
||||
throw new IdentifierException("Trying to save a DOI " +
|
||||
"that is already reserved for another object.");
|
||||
}
|
||||
// safe it to db (see below after end of if-else-statement)
|
||||
}
|
||||
}
|
||||
|
||||
doiRow = DatabaseManager.create(context, "Doi");
|
||||
|
||||
if (null != doi)
|
||||
{
|
||||
doi = doi.substring(DOI.SCHEME.length());
|
||||
|
||||
// check prefix
|
||||
if (!doi.startsWith(this.getPrefix() + "/"))
|
||||
throw new IdentifierException("Trying to create a DOI " +
|
||||
"that's not part of our Namespace!");
|
||||
{
|
||||
throw new DOIIdentifierException("Trying to create a DOI " +
|
||||
"that's not part of our Namespace!",
|
||||
DOIIdentifierException.FOREIGN_DOI);
|
||||
}
|
||||
// prepare new doiRow
|
||||
doiRow = DatabaseManager.create(context, "Doi");
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to generate a new DOI.
|
||||
// We can register a DOI that was not minted, so we can have DOIs
|
||||
// that have not the suffix of the doi_id column.
|
||||
// Generate a new doi_id and check if we already have a DOI with the
|
||||
// same suffix. Try max. THRESHOLD_UNIQUE_DOI times.
|
||||
int i = 0;
|
||||
for ( ; i < THRESHOLD_UNIQUE_DOI ; ++i)
|
||||
{
|
||||
doi = this.getPrefix() + "/" + this.getNamespaceSeparator() +
|
||||
doiRow = DatabaseManager.create(context, "Doi");
|
||||
|
||||
doi = this.getPrefix() + "/" + this.getNamespaceSeparator() +
|
||||
doiRow.getIntColumn("doi_id");
|
||||
if (null == DatabaseManager.findByUnique(context, "Doi", "doi", doi))
|
||||
{
|
||||
break;
|
||||
}
|
||||
doiRow = DatabaseManager.create(context, "Doi");
|
||||
}
|
||||
if (null != DatabaseManager.findByUnique(context, "Doi", "doi", doi))
|
||||
{
|
||||
// We were unable to find a new DOI that does noch already exist.
|
||||
// TODO: throw usefull Exception
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
doiRow.setColumn("doi", doi);
|
||||
doiRow.setColumn("resource_type_id", dso.getType());
|
||||
doiRow.setColumn("resource_id", dso.getID());
|
||||
doiRow.setColumnNull("status");
|
||||
DatabaseManager.update(context, doiRow);
|
||||
if (0 == DatabaseManager.update(context, doiRow))
|
||||
{
|
||||
throw new RuntimeException("Cannot save DOI to databse for unkown reason.");
|
||||
}
|
||||
|
||||
return DOI.SCHEME + doi;
|
||||
return doiRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a DOI out of the metadata of an DSpaceObject.
|
||||
* @param dso
|
||||
* @return The DOI or null if no DOI was found.
|
||||
*/
|
||||
public static String getDOIOutOfObject(DSpaceObject dso) {
|
||||
// FIXME
|
||||
if (!(dso instanceof Item))
|
||||
throw new IllegalArgumentException("Unsupported type " + dso.getTypeText());
|
||||
|
||||
{
|
||||
throw new IllegalArgumentException("We currently support DOIs for "
|
||||
+ "Items only, not for " + dso.getTypeText() + ".");
|
||||
}
|
||||
Item item = (Item)dso;
|
||||
|
||||
DCValue[] metadata = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null);
|
||||
for (DCValue id : metadata)
|
||||
{
|
||||
if (!id.value.startsWith(DOI.SCHEME))
|
||||
if (id.value.startsWith(DOI.SCHEME))
|
||||
{
|
||||
return id.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DOI to the Metadata of an item.
|
||||
* Adds a DOI to the metadata of an item.
|
||||
*
|
||||
* @param context
|
||||
* @param dso DSpaceObject the DOI should be added to.
|
||||
@@ -780,9 +731,12 @@ public class DOIIdentifierProvider
|
||||
{
|
||||
// FIXME
|
||||
if (!(dso instanceof Item))
|
||||
throw new IllegalArgumentException("Unsupported type " + dso.getTypeText());
|
||||
|
||||
{
|
||||
throw new IllegalArgumentException("We currently support DOIs for "
|
||||
+ "Items only, not for " + dso.getTypeText() + ".");
|
||||
}
|
||||
Item item = (Item) dso;
|
||||
|
||||
item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, doi);
|
||||
try
|
||||
{
|
||||
@@ -810,8 +764,10 @@ public class DOIIdentifierProvider
|
||||
{
|
||||
// FIXME
|
||||
if (!(dso instanceof Item))
|
||||
throw new IllegalArgumentException("Unsupported type " + dso.getTypeText());
|
||||
|
||||
{
|
||||
throw new IllegalArgumentException("We currently support DOIs for "
|
||||
+ "Items only, not for " + dso.getTypeText() + ".");
|
||||
}
|
||||
Item item = (Item)dso;
|
||||
|
||||
DCValue[] metadata = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null);
|
||||
@@ -820,7 +776,9 @@ public class DOIIdentifierProvider
|
||||
for (DCValue id : metadata)
|
||||
{
|
||||
if (!id.value.equals(doi))
|
||||
{
|
||||
remainder.add(id.value);
|
||||
}
|
||||
}
|
||||
|
||||
item.clearMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null);
|
||||
|
Reference in New Issue
Block a user