mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-18 15:33:09 +00:00
Continued work on DOIDataCiteIdentifier.
* Added a lot of functionality to DOIDataCiteIdentifierProvider. * Added a table Doi to the database. * Added use of Database table doi to DOIDataCiteIdentifierProvider. * Moved DOIDataCiteIdentifierProvider.DOIToExternalForm(String) to DOI.DOIToExterenalForm.
This commit is contained in:
@@ -17,4 +17,37 @@ public class DOI
|
|||||||
implements Identifier
|
implements Identifier
|
||||||
{
|
{
|
||||||
public static final String SCHEME = "doi:";
|
public static final String SCHEME = "doi:";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method helps to convert a DOI into a URL. It takes DOIs in one of
|
||||||
|
* the following formats and returns it as URL (f.e.
|
||||||
|
* http://dx.doi.org/10.123/456). Allowed formats are:
|
||||||
|
* <ul>
|
||||||
|
* <li>doi:10.123/456</li>
|
||||||
|
* <li>10.123/456</li>
|
||||||
|
* <li>http://dx.doi.org/10.123/456</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param identifier A DOI that should be returned in external form.
|
||||||
|
* @return A String containing a URL to the official DOI resolver.
|
||||||
|
* @throws IllegalArgumentException If identifier is null or an empty String.
|
||||||
|
* @throws IdentifierException If identifier could not be recognized as valid DOI.
|
||||||
|
*/
|
||||||
|
public static String DOIToExternalForm(String identifier)
|
||||||
|
throws IdentifierException
|
||||||
|
{
|
||||||
|
if (null == identifier)
|
||||||
|
throw new IllegalArgumentException("Identifier is null.", new NullPointerException());
|
||||||
|
if (identifier.isEmpty())
|
||||||
|
throw new IllegalArgumentException("Cannot format an empty identifier.");
|
||||||
|
if (identifier.startsWith(SCHEME))
|
||||||
|
return "http://dx.doi.org/" + identifier.substring(SCHEME.length());
|
||||||
|
if (identifier.startsWith("10.") && identifier.contains("/"))
|
||||||
|
return "http://dx.doi.org/" + identifier;
|
||||||
|
if (identifier.startsWith("http://dx.doi.org/10."))
|
||||||
|
return identifier;
|
||||||
|
|
||||||
|
throw new IdentifierException(identifier + "does not seem to be a DOI.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,13 +12,22 @@ import java.io.IOException;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.AuthorizeManager;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.DCValue;
|
import org.dspace.content.DCValue;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.FormatIdentifier;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.ItemIterator;
|
import org.dspace.content.ItemIterator;
|
||||||
|
import org.dspace.content.crosswalk.DisseminationCrosswalk;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.PluginManager;
|
||||||
import org.dspace.identifier.doi.RegistrationAgency;
|
import org.dspace.identifier.doi.RegistrationAgency;
|
||||||
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -51,6 +60,121 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
|
|
||||||
private static final String DOI_SCHEME = DOI.SCHEME;
|
private static final String DOI_SCHEME = DOI.SCHEME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the scheme used to connect to the DataCite server. It will be set
|
||||||
|
* by spring dependency injection.
|
||||||
|
*/
|
||||||
|
private String DATACITE_SCHEME;
|
||||||
|
/**
|
||||||
|
* Stores the hostname of the DataCite server. Set by spring dependency
|
||||||
|
* injection.
|
||||||
|
*/
|
||||||
|
private String DATACITE_HOST;
|
||||||
|
/**
|
||||||
|
* Path on the DataCite server used to generate DOIs. Set by spring
|
||||||
|
* dependency injection.
|
||||||
|
*/
|
||||||
|
private String DATACITE_DOI_PATH;
|
||||||
|
/**
|
||||||
|
* Path on the DataCite server used to register metadata. Set by spring
|
||||||
|
* dependency injection.
|
||||||
|
*/
|
||||||
|
private String DATACITE_METADATA_PATH;
|
||||||
|
/**
|
||||||
|
* Name of crosswalk to convert metadata into DataCite Metadata Scheme. Set
|
||||||
|
* by spring dependency injection.
|
||||||
|
*/
|
||||||
|
protected String CROSSWALK_NAME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix of DOI namespace. Set in dspace.cfg.
|
||||||
|
*/
|
||||||
|
protected String PREFIX;
|
||||||
|
/**
|
||||||
|
* Part of DOI to seperate several applications that generate DOIs. F.e. it
|
||||||
|
* could be 'dspace/' if DOIs generated by DSpace should have the form
|
||||||
|
* prefix/dspace/uniqueString. Set it to the empty String if DSpace should
|
||||||
|
* generate DOIs directly after the DOI Prefix. Set in dspace.cfg.
|
||||||
|
*/
|
||||||
|
protected String NAMESPACE_SEPARATOR;
|
||||||
|
|
||||||
|
// TODO: document how exception while initializing the crosswalks will be
|
||||||
|
// handeled.
|
||||||
|
/**
|
||||||
|
* DisseminationCrosswalk to map local metadata into DataCite metadata.
|
||||||
|
* The name of the crosswalk is set by spring dependency injection using
|
||||||
|
* {@link setDisseminationCrosswalk(String) setDisseminationCrosswalk} which
|
||||||
|
* instantiate the crosswalk.
|
||||||
|
*/
|
||||||
|
protected DisseminationCrosswalk crosswalk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set the scheme to connect the DataCite server. Used by spring
|
||||||
|
* dependency injection.
|
||||||
|
* @param DATACITE_SCHEME Probably https or http.
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setDATACITE_SCHEME(String DATACITE_SCHEME) {
|
||||||
|
this.DATACITE_SCHEME = DATACITE_SCHEME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the hostname of the DataCite server. Used by spring dependency
|
||||||
|
* injection.
|
||||||
|
* @param DATACITE_HOST Hostname to connect to register DOIs (f.e. test.datacite.org).
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setDATACITE_HOST(String DATACITE_HOST) {
|
||||||
|
this.DATACITE_HOST = DATACITE_HOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the path on the DataCite server to register DOIs. Used by spring
|
||||||
|
* dependency injection.
|
||||||
|
* @param DATACITE_DOI_PATH Path to register DOIs, f.e. /doi.
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setDATACITE_DOI_PATH(String DATACITE_DOI_PATH) {
|
||||||
|
this.DATACITE_DOI_PATH = DATACITE_DOI_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the path to register metadata on DataCite server. Used by spring
|
||||||
|
* dependency injection.
|
||||||
|
* @param DATACITE_METADATA_PATH Path to register metadata, f.e. /mds.
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setDATACITE_METADATA_PATH(String DATACITE_METADATA_PATH) {
|
||||||
|
this.DATACITE_METADATA_PATH = DATACITE_METADATA_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: document how exception while initializing the crosswalks will be
|
||||||
|
// handeled.
|
||||||
|
/**
|
||||||
|
* Set the name of the dissemination crosswalk used to convert the metadata
|
||||||
|
* into DataCite Metadata Schema. This method tries to initialize the named
|
||||||
|
* crosswalk. Used by spring dependency injection.
|
||||||
|
* @param CROSSWALK_NAME The name of the dissemination crosswalk to use. This
|
||||||
|
* crosswalk must be configured in dspace.cfg.
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setDisseminationCrosswalk(String CROSSWALK_NAME) {
|
||||||
|
this.CROSSWALK_NAME= CROSSWALK_NAME;
|
||||||
|
|
||||||
|
// FIXME add some caching here
|
||||||
|
this.crosswalk = (DisseminationCrosswalk) PluginManager.getNamedPlugin(DisseminationCrosswalk.class, CROSSWALK_NAME);
|
||||||
|
// FIXME handle the case if the crosswalk can't be found
|
||||||
|
if (this.crosswalk == null) {
|
||||||
|
throw new IllegalArgumentException("Can't find crosswalk '" + CROSSWALK_NAME + "'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DOIDataCiteIdentifierProvider() {
|
||||||
|
// FIXME
|
||||||
|
PREFIX = "10.0123";
|
||||||
|
NAMESPACE_SEPARATOR = "DSpace/";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This identifier provider supports identifiers of type
|
* This identifier provider supports identifiers of type
|
||||||
* {@link org.dspace.identifier.DOI}.
|
* {@link org.dspace.identifier.DOI}.
|
||||||
@@ -90,7 +214,8 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
throws IdentifierException
|
throws IdentifierException
|
||||||
{
|
{
|
||||||
String doi = mint(context, dso);
|
String doi = mint(context, dso);
|
||||||
if (null != doi)
|
// register tries to reserve doi if it's not already.
|
||||||
|
// So we don't have to reserve it here.
|
||||||
this.register(context, dso, doi);
|
this.register(context, dso, doi);
|
||||||
return doi;
|
return doi;
|
||||||
}
|
}
|
||||||
@@ -100,10 +225,17 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
throws IdentifierException
|
throws IdentifierException
|
||||||
{
|
{
|
||||||
String doi = formatIdentifier(identifier);
|
String doi = formatIdentifier(identifier);
|
||||||
if (!isDOIReservedForObject(dso, doi))
|
if (isDOIRegistered(dso, doi))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isDOIRegistered(doi))
|
||||||
|
throw new IllegalArgumentException("Trying to register a DOI that is registered for another object.");
|
||||||
|
|
||||||
|
if (!isDOIReserved(dso, doi))
|
||||||
{
|
{
|
||||||
if (isDOIReserved(doi))
|
if (isDOIReserved(doi))
|
||||||
throw new IllegalStateException("Trying to register a DOI that is reserved for another object.");
|
throw new IllegalArgumentException("Trying to register a DOI that is reserved for another object.");
|
||||||
|
|
||||||
if(!reserveDOI(dso, doi))
|
if(!reserveDOI(dso, doi))
|
||||||
throw new IdentifierException("It was impossible to reserve the DOI "
|
throw new IdentifierException("It was impossible to reserve the DOI "
|
||||||
+ doi + ". Take a look into the logs for further details.");
|
+ doi + ". Take a look into the logs for further details.");
|
||||||
@@ -111,9 +243,7 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (registerDOI(dso, doi))
|
if (!registerDOI(context, dso, doi))
|
||||||
saveDOIToObject(context, dso, doi);
|
|
||||||
else
|
|
||||||
throw new IdentifierException("It was impossible to register the DOI "
|
throw new IdentifierException("It was impossible to register the DOI "
|
||||||
+ doi + ". Take a look into the logs for further details.");
|
+ doi + ". Take a look into the logs for further details.");
|
||||||
}
|
}
|
||||||
@@ -124,15 +254,23 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @param dso DSpaceObject the DOI should be reserved for. Some metadata of this object will be send to the registration agency.
|
||||||
|
* @param identifier DOI to register in a format that {@link FormatIdentifier(String)} accepts.
|
||||||
|
* @throws IdentifierException If the format of {@code identifier} was unrecognized or if it was impossible to reserve the DOI (registration agency denied for some reason, see logs).
|
||||||
|
* @throws IllegalArgumentException If {@code identifier} is a DOI already registered for another DSpaceObject then {@code dso}.
|
||||||
|
* @see IdentifierProvider.reserve(Context, DSpaceObject, String)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void reserve(Context context, DSpaceObject dso, String identifier)
|
public void reserve(Context context, DSpaceObject dso, String identifier)
|
||||||
throws IdentifierException
|
throws IdentifierException, IllegalArgumentException
|
||||||
{
|
{
|
||||||
String doi = formatIdentifier(identifier);
|
String doi = formatIdentifier(identifier);
|
||||||
if (!isDOIReservedForObject(dso, doi))
|
if (!isDOIReserved(dso, doi))
|
||||||
{
|
{
|
||||||
if (isDOIReserved(doi))
|
if (isDOIReserved(doi))
|
||||||
throw new IllegalStateException("Trying to register a DOI that is reserved for another object.");
|
throw new IllegalArgumentException("Trying to register a DOI that is reserved for another object.");
|
||||||
if(!reserveDOI(dso, doi))
|
if(!reserveDOI(dso, doi))
|
||||||
throw new IdentifierException("It was impossible to reserve the DOI "
|
throw new IdentifierException("It was impossible to reserve the DOI "
|
||||||
+ doi + ". Take a look into the logs for further details.");
|
+ doi + ". Take a look into the logs for further details.");
|
||||||
@@ -143,8 +281,27 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
public String mint(Context context, DSpaceObject dso)
|
public String mint(Context context, DSpaceObject dso)
|
||||||
throws IdentifierException
|
throws IdentifierException
|
||||||
{
|
{
|
||||||
//TODO
|
String doi = null;
|
||||||
return null;
|
try
|
||||||
|
{
|
||||||
|
doi = getDOIByObject(context, dso);
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
log.error("Error while attemping to retrieve information about a DOI for " + dso.getTypeText() + " with ID " + dso.getID() + ".");
|
||||||
|
throw new RuntimeException("Error while attemping to retrieve information about a DOI for " + dso.getTypeText() + " with ID " + dso.getID() + ".", e);
|
||||||
|
}
|
||||||
|
if (null == doi) {
|
||||||
|
try {
|
||||||
|
doi = createNewIdentifier(context, dso, null);
|
||||||
|
}
|
||||||
|
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 attemping to create a new DOI for " + dso.getTypeText() + " with ID " + dso.getID() + ".", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -152,80 +309,62 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
String... attributes)
|
String... attributes)
|
||||||
throws IdentifierNotFoundException, IdentifierNotResolvableException
|
throws IdentifierNotFoundException, IdentifierNotResolvableException
|
||||||
{
|
{
|
||||||
// TODO check
|
String doi = null;
|
||||||
log.debug("resolve {}", identifier);
|
|
||||||
try {
|
try {
|
||||||
identifier = formatIdentifier(identifier);
|
doi = formatIdentifier(identifier);
|
||||||
} catch (IdentifierException e) {
|
} catch (IdentifierException e) {
|
||||||
throw new IdentifierNotFoundException(e.getMessage());
|
throw new IdentifierNotResolvableException(e.getMessage());
|
||||||
}
|
}
|
||||||
log.debug("formated identifier as {}", identifier);
|
try
|
||||||
|
{
|
||||||
ItemIterator found;
|
return getObjectByDOI(context, doi);
|
||||||
try {
|
|
||||||
found = Item.findByMetadataField(context,
|
|
||||||
MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER,
|
|
||||||
identifier);
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
log.error(ex.getMessage());
|
|
||||||
throw new IdentifierNotResolvableException(ex);
|
|
||||||
} catch (AuthorizeException ex) {
|
|
||||||
log.error(ex.getMessage());
|
|
||||||
throw new IdentifierNotResolvableException(ex);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
log.error(ex.getMessage());
|
|
||||||
throw new IdentifierNotResolvableException(ex);
|
|
||||||
}
|
}
|
||||||
try {
|
catch (SQLException e)
|
||||||
if (!found.hasNext())
|
{
|
||||||
throw new IdentifierNotFoundException("No object bound to " + identifier);
|
throw new RuntimeException("Unable to retrieve information about a DOI out of database.", e);
|
||||||
Item found1 = found.next();
|
}
|
||||||
if (found.hasNext())
|
catch (IdentifierException e)
|
||||||
log.error("More than one object bound to {}!", identifier);
|
{
|
||||||
log.debug("Resolved to {}", found1);
|
throw new IdentifierNotResolvableException(e);
|
||||||
return found1;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
log.error(ex.getMessage());
|
|
||||||
throw new IdentifierNotResolvableException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String lookup(Context context, DSpaceObject object)
|
public String lookup(Context context, DSpaceObject dso)
|
||||||
throws IdentifierNotFoundException, IdentifierNotResolvableException
|
throws IdentifierNotFoundException, IdentifierNotResolvableException
|
||||||
{
|
{
|
||||||
// TODO: check
|
String doi = null;
|
||||||
log.debug("lookup {}", object);
|
try
|
||||||
|
|
||||||
if (!(object instanceof Item))
|
|
||||||
throw new IllegalArgumentException("Unsupported type " + object.getTypeText());
|
|
||||||
|
|
||||||
Item item = (Item)object;
|
|
||||||
DCValue found = null;
|
|
||||||
for (DCValue candidate : item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null))
|
|
||||||
if (candidate.value.startsWith(DOI_SCHEME))
|
|
||||||
{
|
{
|
||||||
found = candidate;
|
doi = getDOIByObject(context, dso);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (null != found)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
log.debug("Found {}", found.value);
|
throw new RuntimeException("Error retrieving DOI out of database.", e);
|
||||||
return found.value;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
throw new IdentifierNotFoundException(object.getTypeText() + " "
|
if (null == doi)
|
||||||
+ object.getID() + " has no DOI");
|
throw new IdentifierNotFoundException("No DOI for DSpaceObject of type "
|
||||||
|
+ dso.getTypeText() + " with ID " + dso.getID() + " found.");
|
||||||
|
|
||||||
|
return doi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Context context, DSpaceObject dso)
|
public void delete(Context context, DSpaceObject dso)
|
||||||
throws IdentifierException
|
throws IdentifierException
|
||||||
{
|
{
|
||||||
String[] DOIs = getDOIsByObject(dso);
|
String doi = null;
|
||||||
for (String doi : DOIs) {
|
try {
|
||||||
this.delete(context, dso, doi);
|
doi = getDOIByObject(context, dso);
|
||||||
}
|
}
|
||||||
|
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());
|
||||||
|
throw new RuntimeException("Error while attemping to retrieve information about a DOI for " + dso.getTypeText() + " with ID " + dso.getID() + ".", e);
|
||||||
|
}
|
||||||
|
this.delete(context, dso, doi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -236,54 +375,70 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
String doi = formatIdentifier(identifier);
|
String doi = formatIdentifier(identifier);
|
||||||
log.debug("formated identifier as {}", doi);
|
log.debug("formated identifier as {}", doi);
|
||||||
|
|
||||||
if (!deleteDOI(dso, doi))
|
if (isDOIRegistered(doi))
|
||||||
throw new IdentifierException("Unable to delete DOI " + doi +
|
throw new IdentifierException("Unable to delete DOI " + doi +
|
||||||
". Was it already registered? Take a look into the logs for further details.");
|
". It is already registered.");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
catch (SQLException ex)
|
||||||
|
{
|
||||||
|
log.error("SQLException occured while deleting a DOI out of an item: " + ex.getMessage());
|
||||||
|
throw new RuntimeException("Error while deleting a DOI out of the metadata of an Item " + dso.getID(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deleteDOI(context, dso, doi))
|
||||||
|
{
|
||||||
|
// It was not possible to delete a DOI at the registry agency. We
|
||||||
|
// already removed the DOI out of the metadata of the object,
|
||||||
|
// so we should restore these information.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
deleteDOIFromObject(context, dso, doi);
|
saveDOIToObject(context, dso, doi);
|
||||||
}
|
}
|
||||||
// TODO: better Exception handling.
|
catch (AuthorizeException e)
|
||||||
catch (Exception e)
|
|
||||||
{
|
{
|
||||||
throw new IdentifierException(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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Deleted {}", doi);
|
log.info("Deleted {}", doi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method helps to convert a DOI into a URL. It takes DOIs with or
|
|
||||||
* without leading DOI scheme (f.e. doi:10.123/456 as well as 10.123/456)
|
|
||||||
* and returns it as URL (f.e. http://dx.doi.org/10.123/456).
|
|
||||||
*
|
|
||||||
* @param id A DOI that should be returned in external form.
|
|
||||||
* @return A String containing a URL to the official DOI resolver.
|
|
||||||
* @throws IdentifierException
|
|
||||||
*/
|
|
||||||
public static String DOIToExternalForm(String id) throws IdentifierException{
|
|
||||||
if (id.startsWith("http://dx.doi.org/10.")) {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
String doi = formatIdentifier(id);
|
|
||||||
return "http://dx.doi.org/" + doi.substring(DOI_SCHEME.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format any accepted identifier with DOI scheme.
|
* Recognize format of DOI and return it with leading doi-Scheme.
|
||||||
* @param identifier Identifier to format, following format are accepted: f.e. 10.123/456, doi:10.123/456, http://dx.doi.org/10.123/456.
|
* @param identifier Identifier to format, following format are accepted: f.e. 10.123/456, doi:10.123/456, http://dx.doi.org/10.123/456.
|
||||||
* @return Given Identifier with DOI-Scheme, f.e. doi:10.123/456.
|
* @return Given Identifier with DOI-Scheme, f.e. doi:10.123/456.
|
||||||
* @throws IdentifierException
|
* @throws IllegalArgumentException If identifier is empty or null.
|
||||||
|
* @throws IdentifierException If DOI could not be recognized.
|
||||||
*/
|
*/
|
||||||
public static String formatIdentifier(String identifier) throws IdentifierException
|
public static String formatIdentifier(String identifier) throws IdentifierException
|
||||||
{
|
{
|
||||||
if (null == identifier)
|
if (null == identifier)
|
||||||
throw new IdentifierException("Identifier is null.", new NullPointerException());
|
throw new IllegalArgumentException("Identifier is null.", new NullPointerException());
|
||||||
if (identifier.isEmpty())
|
|
||||||
throw new IdentifierException("Cannot format an empty identifier.");
|
|
||||||
if (identifier.startsWith("doi:"))
|
if (identifier.startsWith("doi:"))
|
||||||
return identifier;
|
return identifier;
|
||||||
|
if (identifier.isEmpty())
|
||||||
|
throw new IllegalArgumentException("Cannot format an empty identifier.");
|
||||||
if (identifier.startsWith("10.") && identifier.contains("/"))
|
if (identifier.startsWith("10.") && identifier.contains("/"))
|
||||||
return DOI_SCHEME + identifier;
|
return DOI_SCHEME + identifier;
|
||||||
if (identifier.startsWith("http://dx.doi.org/10."))
|
if (identifier.startsWith("http://dx.doi.org/10."))
|
||||||
@@ -293,36 +448,231 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
|
|
||||||
protected boolean reserveDOI(DSpaceObject dso, String doi)
|
protected boolean reserveDOI(DSpaceObject dso, String doi)
|
||||||
{
|
{
|
||||||
|
// send metadata as post to mds/metadata
|
||||||
|
// 400 -> invalid XML
|
||||||
|
// 401 -> no login
|
||||||
|
// 403 -> wrong credentials or datasets belong to another party
|
||||||
|
// 201 -> created / ok
|
||||||
|
// 500 -> try again later / internal server error
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isDOIReserved(String doi)
|
protected boolean isDOIReserved(String doi)
|
||||||
{
|
{
|
||||||
return true;
|
return isDOIReserved(null, doi);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isDOIReservedForObject(DSpaceObject dso, String doi)
|
protected boolean isDOIReserved(DSpaceObject dso, String doi)
|
||||||
{
|
{
|
||||||
|
// get mds/metadata/<doi>
|
||||||
|
// 410 GONE -> inactive (not clear if ever registered or reserved and deleted)
|
||||||
|
// 404 Not Found -> not reserved
|
||||||
|
// 401 -> no login
|
||||||
|
// 403 -> wrong credential or doi belongs to another party.
|
||||||
|
// 400 -> Bad Content -> f.e. non existing prefix
|
||||||
|
// 500 -> try again later or doi belongs to another registry agency
|
||||||
|
// 200 -> registered and reserved
|
||||||
|
// 204 no content -> reserved but not registered
|
||||||
|
// if (204 && dso != null) -> get mds/doi/<doi> and compare xml->alternative identifier
|
||||||
|
// if (200 && dso != null) -> compare url (out of response-content) with dso
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean registerDOI(DSpaceObject dso, String doi)
|
protected boolean isDOIRegistered(String doi)
|
||||||
{
|
{
|
||||||
|
return isDOIRegistered(null, doi);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isDOIRegistered(DSpaceObject dso, String doi)
|
||||||
|
{
|
||||||
|
// get mds/doi/<doi>
|
||||||
|
// 404 -> not reservered, not registered
|
||||||
|
// 204 -> reserved, not registered
|
||||||
|
// 200 -> reserved, registered
|
||||||
|
// if dso != null && response-code == 200 -> compare url and response
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean deleteDOI(DSpaceObject dso, String doi)
|
|
||||||
|
protected boolean registerDOI(Context context, DSpaceObject dso, String doi)
|
||||||
|
throws SQLException
|
||||||
{
|
{
|
||||||
|
// send doi=<doi>\nurl=<url> to mds/doi
|
||||||
|
// 412 -> prediction failed -> not reserved
|
||||||
|
// 403 -> wrong credential, quota exceeded
|
||||||
|
// 401 -> no login
|
||||||
|
// 400 -> wrong domain, wrong prefix, wrong request body
|
||||||
|
// 201 -> created/updated
|
||||||
|
// 500 -> try again later / internal server error
|
||||||
|
|
||||||
|
// saveDOIToObject(context, dso, doi);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String[] getDOIsByObject(DSpaceObject dso)
|
protected boolean deleteDOI(Context context, DSpaceObject dso, String doi)
|
||||||
throws IdentifierException
|
|
||||||
{
|
{
|
||||||
// TODO
|
if (isDOIRegistered(doi))
|
||||||
return (new String[0]);
|
return false;
|
||||||
|
|
||||||
|
// look for doi in DB
|
||||||
|
// if it exists compare resource type and id
|
||||||
|
// if not okay throw exception
|
||||||
|
|
||||||
|
// delete mds/metadata/<doi>
|
||||||
|
// 200 -> ok
|
||||||
|
// 401 -> no login
|
||||||
|
// 403 -> wrong credential or doi belongs another party
|
||||||
|
// 404 -> doi neither reserved nor registered
|
||||||
|
// 500 -> internal server error
|
||||||
|
|
||||||
|
// delete doi from database
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a DSpaceObject depending on its DOI.
|
||||||
|
* @param context the context
|
||||||
|
* @param identifier The DOI in a format that is accepted by
|
||||||
|
* {@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
|
||||||
|
{
|
||||||
|
String doi = formatIdentifier(identifier);
|
||||||
|
TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi);
|
||||||
|
|
||||||
|
if (null == doiRow)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (doiRow.isColumnNull("resource_type_id") ||
|
||||||
|
doiRow.isColumnNull("resource_id"))
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Found DOI " + doi +
|
||||||
|
" in database, but no assigned Object could be found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return DSpaceObject.find(context,
|
||||||
|
doiRow.getIntColumn("resource_type_id"),
|
||||||
|
doiRow.getIntColumn("resource_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search the database for a DOI, using the type and id of an DSpaceObject.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param dso DSpaceObject to find doi for.
|
||||||
|
* @return The DOI as String or null if DOI was not found.
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public static String getDOIByObject(Context context, DSpaceObject dso)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
String sql = "SELECT * FROM Doi WHERE resource_type_id = ? " +
|
||||||
|
"AND resource_id = ?";
|
||||||
|
|
||||||
|
TableRow doiRow = DatabaseManager.querySingleTable(context, "Doi", sql, dso.getType(), dso.getID());
|
||||||
|
if (null == doiRow)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (doiRow.isColumnNull("doi"))
|
||||||
|
{
|
||||||
|
log.error("A DOI with an empty doi column was found in the database. DSO-Type: "
|
||||||
|
+ dso.getTypeText() + ", ID: " + dso.getID() + ".");
|
||||||
|
throw new IllegalStateException("A DOI with an empty doi column was found in the database. DSO-Type: "
|
||||||
|
+ dso.getTypeText() + ", ID: " + dso.getID() + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return DOI_SCHEME + doiRow.getStringColumn("doi");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DOI and saves it into the database.
|
||||||
|
*
|
||||||
|
* @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 @doi if it was saved into the database.
|
||||||
|
* @throws SQLException In case of an error using the database.
|
||||||
|
* @throws IllegalArgumentException If the given DOI already exists for an other object.
|
||||||
|
*/
|
||||||
|
protected String createNewIdentifier(Context context, DSpaceObject dso, String doi)
|
||||||
|
throws SQLException, IllegalArgumentException
|
||||||
|
{
|
||||||
|
TableRow doiRow = null;
|
||||||
|
if (null != doi)
|
||||||
|
{
|
||||||
|
// 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()));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Trying to save a DOI that is already reserved for another object.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// doi is not null but was not found in db
|
||||||
|
// check if it registered online
|
||||||
|
if (isDOIRegistered(doi) || isDOIReserved(doi))
|
||||||
|
throw new IllegalArgumentException("Trying to save a DOI that is already reserved for another object.");
|
||||||
|
// safe it to db (see below)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doiRow = DatabaseManager.create(context, "Doi");
|
||||||
|
if (null != doi)
|
||||||
|
{
|
||||||
|
doi = doi.substring(DOI_SCHEME.length());
|
||||||
|
if (!doi.startsWith(PREFIX + "/"))
|
||||||
|
throw new IllegalArgumentException("Trying to create a DOI that's not part of our Namespace!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
doi = PREFIX + "/" + NAMESPACE_SEPARATOR + doiRow.getIntColumn("doi_id");
|
||||||
|
doiRow.setColumn("doi", doi);
|
||||||
|
doiRow.setColumn("resource_type_id", dso.getType());
|
||||||
|
doiRow.setColumn("resource_id", dso.getID());
|
||||||
|
DatabaseManager.update(context, doiRow);
|
||||||
|
|
||||||
|
return DOI_SCHEME + doi;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDOIOutOfObject(DSpaceObject dso) {
|
||||||
|
// FIXME
|
||||||
|
if (!(dso instanceof Item))
|
||||||
|
throw new IllegalArgumentException("Unsupported type " + 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))
|
||||||
|
return id.value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a DOI to the Metadata of an item.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param dso DSpaceObject the DOI should be added to.
|
||||||
|
* @param doi The DOI that should be added as metadata.
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws AuthorizeException
|
||||||
|
*/
|
||||||
protected void saveDOIToObject(Context context, DSpaceObject dso, String doi)
|
protected void saveDOIToObject(Context context, DSpaceObject dso, String doi)
|
||||||
throws SQLException, AuthorizeException
|
throws SQLException, AuthorizeException
|
||||||
{
|
{
|
||||||
@@ -344,7 +694,16 @@ public class DOIDataCiteIdentifierProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteDOIFromObject(Context context, DSpaceObject dso, String doi)
|
/**
|
||||||
|
* Removes a DOI out of the metadata of a DSpaceObject.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param dso The DSpaceObject the DOI should be removed from.
|
||||||
|
* @param doi The DOI to remove out of the metadata.
|
||||||
|
* @throws AuthorizeException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
protected void removeDOIFromObject(Context context, DSpaceObject dso, String doi)
|
||||||
throws AuthorizeException, SQLException
|
throws AuthorizeException, SQLException
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME
|
||||||
|
@@ -64,6 +64,7 @@ DROP TABLE TasklistItem;
|
|||||||
DROP TABLE WorkflowItem;
|
DROP TABLE WorkflowItem;
|
||||||
DROP TABLE WorkspaceItem;
|
DROP TABLE WorkspaceItem;
|
||||||
DROP TABLE Handle;
|
DROP TABLE Handle;
|
||||||
|
DROP TABLE Doi;
|
||||||
DROP TABLE EPersonGroup2EPerson;
|
DROP TABLE EPersonGroup2EPerson;
|
||||||
DROP TABLE ResourcePolicy;
|
DROP TABLE ResourcePolicy;
|
||||||
DROP TABLE Collection2Item;
|
DROP TABLE Collection2Item;
|
||||||
@@ -114,6 +115,7 @@ DROP SEQUENCE collection2item_seq;
|
|||||||
DROP SEQUENCE resourcepolicy_seq;
|
DROP SEQUENCE resourcepolicy_seq;
|
||||||
DROP SEQUENCE epersongroup2eperson_seq;
|
DROP SEQUENCE epersongroup2eperson_seq;
|
||||||
DROP SEQUENCE handle_seq;
|
DROP SEQUENCE handle_seq;
|
||||||
|
DROP SEQUENCE doi_seq;
|
||||||
DROP SEQUENCE workspaceitem_seq;
|
DROP SEQUENCE workspaceitem_seq;
|
||||||
DROP SEQUENCE workflowitem_seq;
|
DROP SEQUENCE workflowitem_seq;
|
||||||
DROP SEQUENCE tasklistitem_seq;
|
DROP SEQUENCE tasklistitem_seq;
|
||||||
|
@@ -102,6 +102,7 @@ CREATE SEQUENCE collection2item_seq;
|
|||||||
CREATE SEQUENCE resourcepolicy_seq;
|
CREATE SEQUENCE resourcepolicy_seq;
|
||||||
CREATE SEQUENCE epersongroup2eperson_seq;
|
CREATE SEQUENCE epersongroup2eperson_seq;
|
||||||
CREATE SEQUENCE handle_seq;
|
CREATE SEQUENCE handle_seq;
|
||||||
|
CREATE SEQUENCE doi_seq;
|
||||||
CREATE SEQUENCE workspaceitem_seq;
|
CREATE SEQUENCE workspaceitem_seq;
|
||||||
CREATE SEQUENCE workflowitem_seq;
|
CREATE SEQUENCE workflowitem_seq;
|
||||||
CREATE SEQUENCE tasklistitem_seq;
|
CREATE SEQUENCE tasklistitem_seq;
|
||||||
@@ -492,6 +493,22 @@ CREATE INDEX handle_handle_idx ON Handle(handle);
|
|||||||
-- index by resource id and resource type id
|
-- index by resource id and resource type id
|
||||||
CREATE INDEX handle_resource_id_and_type_idx ON handle(resource_id, resource_type_id);
|
CREATE INDEX handle_resource_id_and_type_idx ON handle(resource_id, resource_type_id);
|
||||||
|
|
||||||
|
-------------------------------------------------------
|
||||||
|
-- Doi table
|
||||||
|
-------------------------------------------------------
|
||||||
|
CREATE TABLE Doi
|
||||||
|
(
|
||||||
|
doi_id INTEGER PRIMARY KEY,
|
||||||
|
doi VARCHAR(256),
|
||||||
|
resource_type_id INTEGER,
|
||||||
|
resource_id INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- index by handle, commonly looked up
|
||||||
|
CREATE INDEX doi_doi_idx ON Doi(doi);
|
||||||
|
-- index by resource id and resource type id
|
||||||
|
CREATE INDEX doi_resource_id_and_type_idx ON Doi(resource_id, resource_type_id);
|
||||||
|
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
-- WorkspaceItem table
|
-- WorkspaceItem table
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
@@ -55,6 +55,7 @@ CREATE SEQUENCE collection2item_seq;
|
|||||||
CREATE SEQUENCE resourcepolicy_seq;
|
CREATE SEQUENCE resourcepolicy_seq;
|
||||||
CREATE SEQUENCE epersongroup2eperson_seq;
|
CREATE SEQUENCE epersongroup2eperson_seq;
|
||||||
CREATE SEQUENCE handle_seq;
|
CREATE SEQUENCE handle_seq;
|
||||||
|
CREATE SEQUENCE doi_seq;
|
||||||
CREATE SEQUENCE workspaceitem_seq;
|
CREATE SEQUENCE workspaceitem_seq;
|
||||||
CREATE SEQUENCE workflowitem_seq;
|
CREATE SEQUENCE workflowitem_seq;
|
||||||
CREATE SEQUENCE tasklistitem_seq;
|
CREATE SEQUENCE tasklistitem_seq;
|
||||||
@@ -444,6 +445,20 @@ CREATE TABLE Handle
|
|||||||
-- index by resource id and resource type id
|
-- index by resource id and resource type id
|
||||||
CREATE INDEX handle_resource_id_type_idx ON handle(resource_id, resource_type_id);
|
CREATE INDEX handle_resource_id_type_idx ON handle(resource_id, resource_type_id);
|
||||||
|
|
||||||
|
-------------------------------------------------------
|
||||||
|
-- Doi table
|
||||||
|
-------------------------------------------------------
|
||||||
|
CREATE TABLE Doi
|
||||||
|
(
|
||||||
|
doi_id INTEGER PRIMARY KEY,
|
||||||
|
doi VARCHAR2(256) UNIQUE,
|
||||||
|
resource_type_id INTEGER,
|
||||||
|
resource_id INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- index by resource id and resource type id
|
||||||
|
CREATE INDEX doi_resource_id_type_idx ON doi(resource_id, resource_type_id);
|
||||||
|
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
-- WorkspaceItem table
|
-- WorkspaceItem table
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
@@ -93,6 +93,7 @@ CREATE SEQUENCE collection2item_seq;
|
|||||||
CREATE SEQUENCE resourcepolicy_seq;
|
CREATE SEQUENCE resourcepolicy_seq;
|
||||||
CREATE SEQUENCE epersongroup2eperson_seq;
|
CREATE SEQUENCE epersongroup2eperson_seq;
|
||||||
CREATE SEQUENCE handle_seq;
|
CREATE SEQUENCE handle_seq;
|
||||||
|
CREATE SEQUENCE doi_seq;
|
||||||
CREATE SEQUENCE workspaceitem_seq;
|
CREATE SEQUENCE workspaceitem_seq;
|
||||||
CREATE SEQUENCE workflowitem_seq;
|
CREATE SEQUENCE workflowitem_seq;
|
||||||
CREATE SEQUENCE tasklistitem_seq;
|
CREATE SEQUENCE tasklistitem_seq;
|
||||||
@@ -485,6 +486,22 @@ CREATE INDEX handle_handle_idx ON Handle(handle);
|
|||||||
-- index by resource id and resource type id
|
-- index by resource id and resource type id
|
||||||
CREATE INDEX handle_resource_id_and_type_idx ON handle(resource_id, resource_type_id);
|
CREATE INDEX handle_resource_id_and_type_idx ON handle(resource_id, resource_type_id);
|
||||||
|
|
||||||
|
-------------------------------------------------------
|
||||||
|
-- Doi table
|
||||||
|
-------------------------------------------------------
|
||||||
|
CREATE TABLE Doi
|
||||||
|
(
|
||||||
|
doi_id INTEGER PRIMARY KEY,
|
||||||
|
doi VARCHAR(256) UNIQUE,
|
||||||
|
resource_type_id INTEGER,
|
||||||
|
resource_id INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- index by handle, commonly looked up
|
||||||
|
CREATE INDEX doi_doi_idx ON Doi(doi);
|
||||||
|
-- index by resource id and resource type id
|
||||||
|
CREATE INDEX doi_resource_id_and_type_idx ON Doi(resource_id, resource_type_id);
|
||||||
|
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
-- WorkspaceItem table
|
-- WorkspaceItem table
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user