/*******************************************************************************
* Australian National University Data Commons
* Copyright (C) 2013 The Australian National University
*
* This file is part of Australian National University Data Commons.
*
* Australian National University Data Commons is free software: you
* can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package au.edu.anu.datacommons.doi;
import static java.text.MessageFormat.format;
import java.util.ArrayList;
import java.util.List;
import org.datacite.schema.kernel_2.DescriptionType;
import org.datacite.schema.kernel_2.Resource;
import org.datacite.schema.kernel_2.Resource.AlternateIdentifiers;
import org.datacite.schema.kernel_2.Resource.Contributors;
import org.datacite.schema.kernel_2.Resource.Creators;
import org.datacite.schema.kernel_2.Resource.Creators.Creator;
import org.datacite.schema.kernel_2.Resource.Dates;
import org.datacite.schema.kernel_2.Resource.Descriptions;
import org.datacite.schema.kernel_2.Resource.Descriptions.Description;
import org.datacite.schema.kernel_2.Resource.Formats;
import org.datacite.schema.kernel_2.Resource.Identifier;
import org.datacite.schema.kernel_2.Resource.RelatedIdentifiers;
import org.datacite.schema.kernel_2.Resource.ResourceType;
import org.datacite.schema.kernel_2.Resource.Sizes;
import org.datacite.schema.kernel_2.Resource.Subjects;
import org.datacite.schema.kernel_2.Resource.Titles;
import org.datacite.schema.kernel_2.Resource.Titles.Title;
import org.datacite.schema.kernel_2.TitleType;
import au.edu.anu.datacommons.xml.data.Data;
import au.edu.anu.datacommons.xml.data.DataItem;
/**
* This class accepts a Data item and creates a new {@link Resource} object with the details of the record. The Resource
* object can then be marshalled into XML as per DataCite's schema used in DOI requests.
*
* @author Rahul Khanna
*
*/
public class DoiResourceAdapter {
private Data sourceData;
private Resource doiResource = new Resource();
/**
* Constructor specifying the Data object to adapt into a Resource object.
*
* @param sourceData
* Data object to read metadata values of a record from.
* @throws DoiException
* when unable to generate a Resource object.
*
*/
public DoiResourceAdapter(Data sourceData) {
this.sourceData = sourceData;
}
/**
* Returns the generated Resource object containing values read from the Data object for use in DOI requests.
*
* @return Resource object containing metadata values of a record
* @throws DoiException
*/
public Resource createDoiResource() throws DoiException {
generateResource();
return this.doiResource;
}
/**
* Generates a Resource object from a specified Data object.
*
* @param itemData
* Data object to read metadata values of a record from.
*
* @throws DoiException
* When at least one creator and one title, a publisher and publication year has not been specified in
* the record.
*/
private void generateResource() throws DoiException {
// Mandatory fields.
Creators creators = getCreators();
if (creators == null) {
throw new DoiException(
"No creators provided. Creators, titles, publisher and publication year are required for a DOI to be minted.");
}
doiResource.setCreators(creators);
Titles titles = getTitles();
if (titles == null) {
throw new DoiException(
"No titles provided. Creators, titles, publisher and publication year are required for a DOI to be minted.");
}
doiResource.setTitles(titles);
String publisher = getPublisher();
if (publisher == null) {
throw new DoiException(
"No publisher provided. Creators, titles, publisher and publication year are required for a DOI to be minted.");
}
doiResource.setPublisher(publisher);
String publicationYear = getPublicationYear();
if (publicationYear == null) {
throw new DoiException(
"No publication year provided. Creators, titles, publisher and publication year are required for a DOI to be minted.");
}
doiResource.setPublicationYear(publicationYear);
// Optional fields.
doiResource.setSubjects(getSubjects());
doiResource.setContributors(getContributors());
doiResource.setDates(getDates());
doiResource.setLanguage(getLanguage());
doiResource.setResourceType(getResourceType());
doiResource.setIdentifier(getIdentifier());
doiResource.setAlternateIdentifiers(getAlternateIdentifiers());
doiResource.setRelatedIdentifiers(getRelatedIdentifiers());
doiResource.setSizes(getSizes());
doiResource.setFormats(getFormats());
doiResource.setVersion(getVersion());
doiResource.setRights(getRights());
doiResource.setDescriptions(getDescriptions());
}
/**
* Returns a Creators object consisting of a list of Creator objects created from the specified Data object.
*
* @param itemData
* Data object containing a record's metadata.
* @return Creators object containing a List of Creator objects
*/
private Creators getCreators() {
Creators creators = null;
List<Creator> list = new ArrayList<Creator>();
List<DataItem> dataItems = sourceData.getElementByName("citCreator");
for (DataItem item : dataItems) {
if (item.getChildValues() != null && item.getChildValues().size() > 0) {
Creator c = new Creator();
String creatorGiven = null;
String creatorSurname = null;
for (DataItem childItem : item.getChildValues()) {
if ("citCreatorGiven".equals(childItem.getName())) {
creatorGiven = childItem.getValue();
}
else if ("citCreatorSurname".equals(childItem.getName())) {
creatorSurname = childItem.getValue();
}
}
c.setCreatorName(format("{0} {1}", creatorGiven, creatorSurname));
list.add(c);
}
}
if (!list.isEmpty()) {
creators = new Creators();
creators.getCreator().addAll(list);
}
return creators;
}
/**
* Returns a Titles object consisting of a list of Title objects from the specified Data object.
*
* @param itemData
* Data object to read title details from
* @return Titles object containing a List of Title objects.
*/
private Titles getTitles() {
Titles titles = null;
List<Title> list = new ArrayList<Title>();
String titleStr = getValueOfFirstElementByNameFromSource("name");
if (titleStr != null) {
Title t = new Title();
t.setValue(titleStr);
list.add(t);
}
String altTitleStr = getValueOfFirstElementByNameFromSource("altName");
if (altTitleStr != null) {
Title t = new Title();
t.setValue(altTitleStr);
t.setTitleType(TitleType.ALTERNATIVE_TITLE);
list.add(t);
}
if (list.size() > 0) {
titles = new Titles();
titles.getTitle().addAll(list);
}
return titles;
}
/**
* Gets the publisher of the record from the Data object.
*
* @param itemData
* Data object from which the publisher value will be read
* @return Name of Publisher as String
*/
private String getPublisher() {
return getValueOfFirstElementByNameFromSource("citationPublisher");
}
/**
* Gets the year of publication from the Data Object.
*
* @param itemData
* Data object from which the year of publication will be read
* @return Year of publication as String
*/
private String getPublicationYear() {
return getValueOfFirstElementByNameFromSource("citationYear");
}
private Subjects getSubjects() {
// TODO Implement.
return null;
}
private Contributors getContributors() {
// TODO Implement.
return null;
}
private Dates getDates() {
// TODO Implement.
return null;
}
/**
* Gets the language of the metadata.
*
* @return Language as String
*/
private String getLanguage() {
return getValueOfFirstElementByNameFromSource("metaLang");
}
/**
* Maps the resource to one allowed by DataCite schema. Since DataCommons only recognises collections or datasets,
* only one of those two values will be returned.
*
* @return ResourceType object
*/
private ResourceType getResourceType() {
ResourceType resType = null;
DataItem subTypeDI = this.sourceData.getFirstElementByName("subType");
String subType = subTypeDI.getValue().toLowerCase();
if (subType.equals("dataset")) {
resType = new ResourceType();
resType.setResourceTypeGeneral(org.datacite.schema.kernel_2.ResourceType.DATASET);
resType.setContent("Dataset");
} else if (subType.equals("collection")) {
resType = new ResourceType();
resType.setResourceTypeGeneral(org.datacite.schema.kernel_2.ResourceType.COLLECTION);
resType.setContent("Collection");
}
return resType;
}
/**
* Gets the DOI identifier if one exists
*
* @return Identifier Object
*/
private Identifier getIdentifier() {
Identifier identifier = null;
String doiStr = getValueOfFirstElementByNameFromSource("doi");
if (doiStr != null && doiStr.length() > 0) {
identifier = new Identifier();
identifier.setValue(doiStr);
identifier.setIdentifierType("DOI");
}
return identifier;
}
private AlternateIdentifiers getAlternateIdentifiers() {
// TODO Implement
return null;
}
private RelatedIdentifiers getRelatedIdentifiers() {
// TODO Implement
return null;
}
private Sizes getSizes() {
// TODO Implement
return null;
}
private Formats getFormats() {
// TODO Implement
return null;
}
private String getVersion() {
// TODO Implement
return null;
}
private String getRights() {
// TODO Implement
return null;
}
/**
* Gets the brief and full descriptions, if exists.
*
* @return Descriptions object
*/
private Descriptions getDescriptions() {
Descriptions descriptions = null;
List<Description> list = new ArrayList<Description>();
String bDesc = getValueOfFirstElementByNameFromSource("briefDesc");
if (bDesc != null) {
Description d = new Description();
d.getContent().add(bDesc);
d.setDescriptionType(DescriptionType.OTHER);
list.add(d);
}
String fDesc = getValueOfFirstElementByNameFromSource("fullDesc");
if (fDesc != null) {
Description d = new Description();
d.getContent().add(fDesc);
d.setDescriptionType(DescriptionType.ABSTRACT);
list.add(d);
}
if (list.size() > 0) {
descriptions = new Descriptions();
descriptions.getDescription().addAll(list);
}
return descriptions;
}
/**
* Gets the value of the first element found with the specified name.
*
* @param elementName
* Element whose value is requested
* @return value as String
*/
private String getValueOfFirstElementByNameFromSource(String elementName) {
String value = null;
DataItem di = this.sourceData.getFirstElementByName(elementName);
if (di != null && di.getValue().length() > 0) {
value = di.getValue();
}
return value;
}
}