/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package edu.harvard.iq.dataverse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.PreDestroy; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /** * * @author luopc */ @Stateless public class DOIDataCiteRegisterService { private static final Logger logger = Logger.getLogger(DOIDataCiteRegisterService.class.getCanonicalName()); @PersistenceContext(unitName = "VDCNet-ejbPU") private EntityManager em; private DataCiteRESTfullClient openClient() throws IOException { return new DataCiteRESTfullClient(System.getProperty("doi.baseurlstring"), System.getProperty("doi.username"), System.getProperty("doi.password")); } public String createIdentifier(String identifier, HashMap<String, String> metadata, Dataset dataset) throws IOException { DataCiteMetadataTemplate metadataTemplate = new DataCiteMetadataTemplate(); metadataTemplate.setIdentifier(identifier.substring(identifier.indexOf(':') + 1)); metadataTemplate.setCreators(Util.getListFromStr(metadata.get("datacite.creator"))); metadataTemplate.setAuthors(dataset.getLatestVersion().getDatasetAuthors()); metadataTemplate.setDescription(dataset.getLatestVersion().getDescription()); metadataTemplate.setContacts(dataset.getLatestVersion().getDatasetContacts()); metadataTemplate.setProducers(dataset.getLatestVersion().getDatasetProducers()); metadataTemplate.setTitle(dataset.getLatestVersion().getTitle()); metadataTemplate.setPublisher(metadata.get("datacite.publisher")); metadataTemplate.setPublisherYear(metadata.get("datacite.publicationyear")); String xmlMetadata = metadataTemplate.generateXML(); String status = metadata.get("_status").trim(); String target = metadata.get("_target"); String retString = ""; if (status.equals("reserved")) { DOIDataCiteRegisterCache rc = findByDOI(identifier); if (rc == null) { rc = new DOIDataCiteRegisterCache(); rc.setDoi(identifier); rc.setXml(xmlMetadata); rc.setStatus("reserved"); rc.setUrl(target); em.persist(rc); } else { rc.setDoi(identifier); rc.setXml(xmlMetadata); rc.setStatus("reserved"); rc.setUrl(target); } retString = "success to reserved " + identifier; } else if (status.equals("public")) { DOIDataCiteRegisterCache rc = findByDOI(identifier); if (rc != null) { rc.setDoi(identifier); rc.setXml(xmlMetadata); rc.setStatus("public"); if (target == null || target.trim().length() == 0) { target = rc.getUrl(); } else { rc.setUrl(target); } try (DataCiteRESTfullClient client = openClient()) { retString = client.postMetadata(xmlMetadata); client.postUrl(identifier.substring(identifier.indexOf(":") + 1), target); } catch (UnsupportedEncodingException ex) { Logger.getLogger(DOIDataCiteRegisterService.class.getName()).log(Level.SEVERE, null, ex); } } } else if (status.equals("unavailable")) { DOIDataCiteRegisterCache rc = findByDOI(identifier); try (DataCiteRESTfullClient client = openClient()) { if (rc != null) { rc.setStatus("unavailable"); retString = client.inactiveDataset(identifier.substring(identifier.indexOf(":") + 1)); } } catch (IOException io) { } } return retString; } public boolean testDOIExists(String identifier) { boolean doiExists; try (DataCiteRESTfullClient client = openClient()) { doiExists = client.testDOIExists(identifier.substring(identifier.indexOf(":") + 1)); } catch (Exception e) { logger.log(Level.INFO, identifier, e); return false; } return doiExists; } public HashMap<String, String> getMetadata(String identifier) throws IOException { HashMap<String, String> metadata = new HashMap(); try (DataCiteRESTfullClient client = openClient()) { String xmlMetadata = client.getMetadata(identifier.substring(identifier.indexOf(":") + 1)); DataCiteMetadataTemplate template = new DataCiteMetadataTemplate(xmlMetadata); metadata.put("datacite.creator", Util.getStrFromList(template.getCreators())); metadata.put("datacite.title", template.getTitle()); metadata.put("datacite.publisher", template.getPublisher()); metadata.put("datacite.publicationyear", template.getPublisherYear()); DOIDataCiteRegisterCache rc = findByDOI(identifier); if (rc != null) { metadata.put("_status", rc.getStatus()); } } catch (RuntimeException e) { logger.log(Level.INFO, identifier, e); } return metadata; } public DOIDataCiteRegisterCache findByDOI(String doi) { Query query = em.createNamedQuery("DOIDataCiteRegisterCache.findByDoi", DOIDataCiteRegisterCache.class); query.setParameter("doi", doi); List<DOIDataCiteRegisterCache> rc = query.getResultList(); if (rc.size() == 1) { return rc.get(0); } return null; } public void deleteIdentifier(String identifier) { DOIDataCiteRegisterCache rc = findByDOI(identifier); if (rc != null) { em.remove(rc); } } } class DataCiteMetadataTemplate { private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.DataCiteMetadataTemplate"); private static String template; static { try (InputStream in = DataCiteMetadataTemplate.class.getResourceAsStream("datacite_metadata_template.xml")) { template = Util.readAndClose(in, "utf-8"); } catch (Exception e) { logger.log(Level.SEVERE, "datacite metadata template load error"); logger.log(Level.SEVERE, "String " + e.toString()); logger.log(Level.SEVERE, "localized message " + e.getLocalizedMessage()); logger.log(Level.SEVERE, "cause " + e.getCause()); logger.log(Level.SEVERE, "message " + e.getMessage()); } } private String xmlMetadata; private String identifier; private List<String> creators; private String title; private String publisher; private String publisherYear; private List<DatasetAuthor> authors; private String description; private List<String[]> contacts; private List<String[]> producers; public List<String[]> getProducers() { return producers; } public void setProducers(List<String[]> producers) { this.producers = producers; } public List<String[]> getContacts() { return contacts; } public void setContacts(List<String[]> contacts) { this.contacts = contacts; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public List<DatasetAuthor> getAuthors() { return authors; } public void setAuthors(List<DatasetAuthor> authors) { this.authors = authors; } public DataCiteMetadataTemplate() { } public DataCiteMetadataTemplate(String xmlMetaData) { this.xmlMetadata = xmlMetaData; Document doc = Jsoup.parseBodyFragment(xmlMetaData); Elements identifierElements = doc.select("identifier"); if (identifierElements.size() > 0) { identifier = identifierElements.get(0).html(); } Elements creatorElements = doc.select("creatorName"); creators = new ArrayList(); for (Element creatorElement : creatorElements) { creators.add(creatorElement.html()); } Elements titleElements = doc.select("title"); if (titleElements.size() > 0) { title = titleElements.get(0).html(); } Elements publisherElements = doc.select("publisher"); if (publisherElements.size() > 0) { publisher = publisherElements.get(0).html(); } Elements publisherYearElements = doc.select("publicationYear"); if (publisherYearElements.size() > 0) { publisherYear = publisherYearElements.get(0).html(); } } public String generateXML() { xmlMetadata = template.replace("${identifier}", this.identifier.trim()) .replace("${title}", this.title) .replace("${publisher}", this.publisher) .replace("${publisherYear}", this.publisherYear) .replace("${description}", this.description); StringBuilder creatorsElement = new StringBuilder(); for (DatasetAuthor author : authors) { creatorsElement.append("<creator><creatorName>"); creatorsElement.append(author.getName().getDisplayValue()); creatorsElement.append("</creatorName>"); if (author.getIdType() != null && author.getIdValue() != null && !author.getIdType().isEmpty() && !author.getIdValue().isEmpty() && author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { if (author.getIdType().equals("ORCID")) { creatorsElement.append("<nameIdentifier schemeURI=\"http://orcid.org/\" nameIdentifierScheme=\"ORCID\">" + author.getIdValue() + "</nameIdentifier>"); } if (author.getIdType().equals("ISNI")) { creatorsElement.append("<nameIdentifier schemeURI=\"http://isni.org/isni/\" nameIdentifierScheme=\"ISNI\">" + author.getIdValue() + "</nameIdentifier>"); } if (author.getIdType().equals("LCNA")) { creatorsElement.append("<nameIdentifier schemeURI=\"http://id.loc.gov/authorities/names/\" nameIdentifierScheme=\"LCNA\">" + author.getIdValue() + "</nameIdentifier>"); } } if (author.getAffiliation() != null && !author.getAffiliation().getDisplayValue().isEmpty()) { creatorsElement.append("<affiliation>" + author.getAffiliation().getDisplayValue() + "</affiliation>"); } creatorsElement.append("</creator>"); } xmlMetadata = xmlMetadata.replace("${creators}", creatorsElement.toString()); StringBuilder contributorsElement = new StringBuilder(); for (String[] contact : this.getContacts()) { contributorsElement.append("<contributor contributorType=\"ContactPerson\"><contributorName>" + contact[0] + "</contributorName>"); if (!contact[1].isEmpty()) { contributorsElement.append("<affiliation>" + contact[1] + "</affiliation>"); } contributorsElement.append("</contributor>"); } for (String[] producer : this.getProducers()) { contributorsElement.append("<contributor contributorType=\"Producer\"><contributorName>" + producer[0] + "</contributorName>"); if (!producer[1].isEmpty()) { contributorsElement.append("<affiliation>" + producer[1] + "</affiliation>"); } contributorsElement.append("</contributor>"); } xmlMetadata = xmlMetadata.replace("{$contributors}", contributorsElement.toString()); return xmlMetadata; } public static String getTemplate() { return template; } public static void setTemplate(String template) { DataCiteMetadataTemplate.template = template; } public String getIdentifier() { return identifier; } public void setIdentifier(String identifier) { this.identifier = identifier; } public List<String> getCreators() { return creators; } public void setCreators(List<String> creators) { this.creators = creators; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public String getPublisherYear() { return publisherYear; } public void setPublisherYear(String publisherYear) { this.publisherYear = publisherYear; } } class Util { public static void close(InputStream in) { if (in != null) { try { in.close(); } catch (IOException e) { throw new RuntimeException("Fail to close InputStream"); } } } public static String readAndClose(InputStream inStream, String encoding) { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buf = new byte[128]; String data; try { int cnt; while ((cnt = inStream.read(buf)) >= 0) { outStream.write(buf, 0, cnt); } data = outStream.toString(encoding); } catch (IOException ioe) { throw new RuntimeException("IOException"); } finally { close(inStream); } return data; } public static List<String> getListFromStr(String str) { return Arrays.asList(str.split("; ")); // List<String> authors = new ArrayList(); // int preIdx = 0; // for(int i=0;i<str.length();i++){ // if(str.charAt(i)==';'){ // authors.add(str.substring(preIdx,i).trim()); // preIdx = i+1; // } // } // return authors; } public static String getStrFromList(List<String> authors) { StringBuilder str = new StringBuilder(); for (String author : authors) { if (str.length() > 0) { str.append("; "); } str.append(author); } return str.toString(); } }