diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java index d3ba300b67..10acba8940 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -73,7 +73,8 @@ public class DOIIdentifierProvider public static final Integer UPDATE_RESERVERED = 5; public static final Integer UPDATE_REGISTERED = 6; public static final Integer UPDATE_BEFORE_REGISTERATION = 7; - public static final Integer DELETED = 8; + public static final Integer TO_BE_DELETED = 8; + public static final Integer DELETED = 9; /** * Prefix of DOI namespace. Set in dspace.cfg. @@ -197,6 +198,7 @@ public class DOIIdentifierProvider doiRow.setColumn("status", TO_BE_REGISTERED); try { DatabaseManager.update(context, doiRow); + context.commit(); } catch (SQLException sqle) { @@ -581,11 +583,11 @@ public class DOIIdentifierProvider { String doi = DOI.formatIdentifier(identifier); TableRow doiRow = null; - String oldStatus = null; try { - doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi.substring(DOI.SCHEME.length())); + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); } catch (SQLException sqle) { @@ -626,6 +628,51 @@ public class DOIIdentifierProvider // change doi status in db if necessary. if (null != doiRow) { + doiRow.setColumn("status", TO_BE_DELETED); + try { + DatabaseManager.update(context, doiRow); + context.commit(); + } + catch (SQLException sqle) + { + log.warn("SQLException while changing status of DOI {} to be deleted.", doi); + throw new RuntimeException(sqle); + } + } + + // DOI is a permanent identifier. DataCite for example does not delete + // DOIS. But it is possible to mark a DOI as "inactive". + } + + public void deleteOnline(Context context, String identifier) + throws DOIIdentifierException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = null; + + try + { + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + } + catch (SQLException sqle) + { + throw new RuntimeException(sqle); + } + if(null == doiRow) + { + throw new DOIIdentifierException("This identifier: " + identifier + + " isn't in our database", + DOIIdentifierException.DOI_DOES_NOT_EXIST); + } + if (TO_BE_DELETED != doiRow.getIntColumn("status")) + { + log.error("This identifier: {} couldn't be deleted", + DOI.SCHEME + doiRow.getStringColumn("doi")); + return; + } + connector.deleteDOI(context, doi); + doiRow.setColumn("status", DELETED); try { DatabaseManager.update(context, doiRow); @@ -633,16 +680,10 @@ public class DOIIdentifierProvider } catch (SQLException sqle) { - log.warn("SQLException while changing status of DOI {} to be registered.", doi); + log.warn("SQLException while changing status of DOI {} deleted.", doi); throw new RuntimeException(sqle); } - } - - // 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); } - /** * Returns a DSpaceObject depending on its DOI. @@ -684,7 +725,7 @@ public class DOIIdentifierProvider * Search the database for a DOI, using the type and id of an DSpaceObject. * * @param context - * @param dso DSpaceObject to find doi for. DOIs with status DELETED will be + * @param dso DSpaceObject to find doi for. DOIs with status TO_BE_DELETED will be * ignored. * @return The DOI as String or null if DOI was not found. * @throws SQLException @@ -693,10 +734,11 @@ public class DOIIdentifierProvider throws SQLException { String sql = "SELECT * FROM Doi WHERE resource_type_id = ? " + - "AND resource_id = ? AND status != ?"; + "AND resource_id = ? AND (status != ? OR status != ?)"; - TableRow doiRow = DatabaseManager.querySingleTable(context, - "Doi", sql, dso.getType(), dso.getID(), DOIIdentifierProvider.DELETED); + TableRow doiRow = DatabaseManager.querySingleTable(context, "Doi", sql, + dso.getType(), dso.getID(), DOIIdentifierProvider.TO_BE_DELETED, + DOIIdentifierProvider.DELETED); if (null == doiRow) { return null; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 5a01651cb3..0391377dcf 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -135,6 +135,14 @@ public class DOIOrganiser { options.addOption(update); + Option delete = OptionBuilder.withArgName("DOI identifier") + .withLongOpt("delete") + .hasArgs(1) + .withDescription("Delete a specified identifier.") + .create('d'); + + options.addOption(delete); + // initialize parser CommandLineParser parser = new PosixParser(); @@ -337,6 +345,35 @@ public class DOIOrganiser { } } } + + if(line.hasOption('d')) + { + String identifier = line.getOptionValue('d'); + + if (null == identifier) + { + helpformater.printHelp("\nDOI organiser\n", options); + } + else { + try { + TableRow doiRow = organiser.findTableRow(identifier); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.delete(doiRow, dso); + } catch (SQLException ex) { + LOG.error(ex); + } catch (IllegalArgumentException ex) { + LOG.error(ex); + } catch (IllegalStateException ex) { + LOG.error(ex); + } catch (IdentifierException ex) { + LOG.error(ex); + } + } + } + } @@ -608,6 +645,54 @@ public class DOIOrganiser { } } + public void delete(TableRow doiRow, DSpaceObject dso) + { + if(null == doiRow) + { + if (!quiet) + { + System.err.println("The DOI identifier that should be deleted doesn't exist."); + } + LOG.error("The DOI identifier that should be deleted doesn't exist."); + + return; + } + try + { + provider.deleteOnline(context, doiRow.getStringColumn("doi")); + + if(!quiet) + { + System.out.println("This identifier : " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " is successfully delete."); + } + } + catch (DOIIdentifierException ex) + { + try + { + sendAlertMail("Delete", dso, + DOI.SCHEME + doiRow.getStringColumn("doi"), + ex.codeToString(ex.getCode())); + } + catch (IOException ioe) + { + LOG.error("Couldn't send mail", ioe); + } + + LOG.error("It wasn't possible to delete the identifier online. " + + " Exceptions code: " + + ex.codeToString(ex.getCode()), ex); + + if(!quiet) + { + System.err.println("It wasn't possible to delete this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + } + } + /** * Finds the TableRow in the Doi table that belongs to the specified * DspaceObject. @@ -665,6 +750,29 @@ public class DOIOrganiser { } } + // detect handle + DSpaceObject dso = HandleManager.resolveToObject(context, identifier); + + if (null != dso) + { + if (dso.getType() != Constants.ITEM) + { + throw new IllegalArgumentException( + "Currently DSpace supports DOIs for Items only. " + + "Cannot process specified handle as it does not identify an Item."); + } + + doiRow = DatabaseManager.querySingleTable(context, "Doi", sql, + Constants.ITEM, dso.getID()); + + if (null == doiRow) + { + doi = provider.mint(context, dso); + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + } + return doiRow; + } // detect DOI try { doi = DOI.formatIdentifier(identifier); @@ -676,37 +784,25 @@ public class DOIOrganiser { throw new IllegalStateException("You specified a valid DOI," + " that is not stored in our database."); } - return doiRow; } catch (DOIIdentifierException ex) { - // Identifier was not recognized as DOI => must be a handle. - // Will check for handle outside try-catch-block... + // Identifier was not recognized as DOI. + LOG.error("It wasn't possible to detect this identifier: " + + identifier + + " Exceptions code: " + + ex.codeToString(ex.getCode()), ex); + + if(!quiet) + { + System.err.println("It wasn't possible to detect this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); } + } - // detect handle - DSpaceObject dso = HandleManager.resolveToObject(context, identifier); - - if (dso.getType() != Constants.ITEM) - { - throw new IllegalArgumentException( - "Currently DSpace supports DOIs for Items only. " - + "Cannot process specified handle as it does not identify an Item."); - } - doiRow = DatabaseManager.querySingleTable(context, "Doi", sql, - Constants.ITEM, dso.getID()); - - if (null == doiRow) - { - doi = provider.mint(context, dso); - doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", - doi.substring(DOI.SCHEME.length())); - - return doiRow; - } return doiRow; - } - + } + private void sendAlertMail(String action, DSpaceObject dso, String doi, String reason) throws IOException {