Add initial code

This commit is contained in:
Mark H. Wood
2012-10-05 13:11:17 -04:00
committed by Pascal-Nicolas Becker
parent 4ebe7217d9
commit e5d53f8f43
3 changed files with 326 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
package org.dspace.identifier;
/**
* DOI identifiers.
*
* @author mwood
*/
public class DOI
implements Identifier
{
}

View File

@@ -0,0 +1,297 @@
/**
* 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.io.IOException;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.httpclient.StatusLine;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
/**
* Provide service for DOIs through DataCite.
*
* @author mwood
*/
public class DataCiteIdentifierProvider
extends IdentifierProvider
{
private static final Logger log = LoggerFactory.getLogger(DataCiteIdentifierProvider.class);
@Override
public boolean supports(Class<? extends Identifier> identifier)
{
return DOI.class.isAssignableFrom(identifier);
}
@Override
public boolean supports(String identifier)
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String register(Context context, DSpaceObject item)
throws IdentifierException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String mint(Context context, DSpaceObject dso)
throws IdentifierException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public DSpaceObject resolve(Context context, String identifier,
String... attributes)
throws IdentifierNotFoundException, IdentifierNotResolvableException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String lookup(Context context, DSpaceObject object)
throws IdentifierNotFoundException, IdentifierNotResolvableException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void delete(Context context, DSpaceObject dso)
throws IdentifierException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void delete(Context context, DSpaceObject dso, String identifier)
throws IdentifierException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void reserve(Context context, DSpaceObject dso, String identifier)
throws IdentifierException
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void register(Context context, DSpaceObject object, String identifier)
{
throw new UnsupportedOperationException("Not supported yet.");
}
private static String EZID_SCHEME; // = "https";
private static String EZID_HOST; // = "n2t.net";
private static String EZID_PATH; // = "/ezid/shoulder/";
/** Map DataCite metadata into local metadata */
private static Map<String, String> crosswalk = new HashMap<String, String>();
/* default mapping */
/*
static
{
crosswalk.put("datacite.creator", "dc.creator.author");
crosswalk.put("datacite.title", "dc.title");
crosswalk.put("datacite.publisher", "dc.publisher");
crosswalk.put("datacite.publicationyear", "dc.date.published");
}
*/
/**
* @param aEZID_SCHEME the EZID URL scheme to set
*/
@Autowired
@Required
public static void setEZID_SCHEME(String aEZID_SCHEME)
{
EZID_SCHEME = aEZID_SCHEME;
}
/**
* @param aEZID_HOST the EZID host to set
*/
@Autowired
@Required
public static void setEZID_HOST(String aEZID_HOST)
{
EZID_HOST = aEZID_HOST;
}
/**
* @param aEZID_PATH the EZID path to set
*/
@Autowired
@Required
public static void setEZID_PATH(String aEZID_PATH)
{
EZID_PATH = aEZID_PATH;
}
/**
* @param aCrosswalk the crosswalk to set
*/
@Autowired
public static void setCrosswalk(Map<String, String> aCrosswalk)
{
crosswalk = aCrosswalk;
}
private static final Pattern DOIpattern = Pattern.compile("doi:[\\S]+");
private static final Pattern ARKpattern = Pattern.compile("ark:[\\S]+");
private static final ContentType CONTENT_UTF8_TEXT = ContentType.create("text/plain", "UTF-8");
private String doi = null;
private String ark = null;
/**
* Submit some object details and request identifiers for the object.
*
* @param postBody the details, formatted for EZID.
*/
public void request(String postBody)
throws IdentifierException
{
// Address the service
URIBuilder mintURL = new URIBuilder();
mintURL.setScheme(EZID_SCHEME)
.setHost(EZID_HOST)
.setPath(EZID_PATH + configurationService.getProperty("identifier.doi.ezid.shoulder"));
// Compose the request
HttpPost request;
try {
request = new HttpPost(mintURL.build());
} catch (URISyntaxException ex) {
log.error(ex.getMessage());
throw new IdentifierException("DOI request not sent: " + ex.getMessage());
}
request.setEntity(new StringEntity(postBody, CONTENT_UTF8_TEXT));
AbstractHttpClient mint = new DefaultHttpClient();
mint.getCredentialsProvider().setCredentials(
new AuthScope(mintURL.getHost(), mintURL.getPort()),
new UsernamePasswordCredentials(
configurationService.getProperty("identifier.doi.ezid.user"),
configurationService.getProperty("identifier.doi.ezid.password")));
// Send the request
HttpResponse response;
try
{
response = mint.execute(request);
} catch (IOException ex)
{
log.error("Failed to send EZID request: {}", ex.getMessage());
throw new IdentifierException("DOI request not sent: " + ex.getMessage());
}
// Good response?
StatusLine status = (StatusLine) response.getStatusLine();
if (HttpURLConnection.HTTP_CREATED != status.getStatusCode())
{
log.error("EZID responded: {} {}", status.getStatusCode(),
status.getReasonPhrase());
throw new IdentifierException("DOI not created: " + status.getReasonPhrase());
}
HttpEntity responseBody = response.getEntity();
// Collect the content of the response
String content;
try {
content = EntityUtils.toString(responseBody, "UTF-8");
} catch (IOException ex) {
log.error(ex.getMessage());
throw new IdentifierException("EZID response not understood: " + ex.getMessage());
} catch (ParseException ex) {
log.error(ex.getMessage());
throw new IdentifierException("EZID response not understood: " + ex.getMessage());
}
// Extract the identifiers from the content blob
Matcher matcher;
// DOI
matcher = DOIpattern.matcher(content);
if (matcher.find())
doi = matcher.group();
// ARK
matcher = ARKpattern.matcher(content);
if (matcher.find())
ark = matcher.group();
}
public String getDoi() { return doi; }
public String getArk() { return ark; }
/**
* Assemble the identifier request document, one field per line.
*
* @param dso the object we want to identify.
*/
static public String generatePostBody(DSpaceObject dso)
{
if ((null == dso) || !(dso instanceof Item))
throw new IllegalArgumentException("Must be an Item");
Item item = (Item) dso; // TODO generalize to DSO when all DSOs have metadata.
StringBuilder bupher = new StringBuilder();
for (Map.Entry<String, String> datum : crosswalk.entrySet())
{
DCValue[] values = item.getMetadata(datum.getValue());
if (null != values)
{
for (DCValue value : values)
{
bupher.append(datum.getKey())
.append(": ")
.append(value.value)
.append('\n');
}
}
}
return bupher.toString();
}
}

View File

@@ -0,0 +1,17 @@
/**
* 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/
*/
/**
* Providers of durable unique identifiers (Handles, DOIs, etc.).
* Generally, subclasses of {@link org.dspace.identifier.IdentifierProvider}
* offer methods to create, delete, and resolve subclasses of
* {@link org.dspace.identifier.Identifier}. Classes outside this package
* should rely on {@link org.dspace.identifier.IdentifierService} to perform
* these operations using the most appropriate provider.
*/
package org.dspace.identifier;