/*******************************************************************************
* 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.external.geographicmetadata;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import javax.xml.bind.JAXBElement;
import org.isotc211._2005.gco.CharacterStringPropertyType;
import org.isotc211._2005.gmd.CICitationType;
import org.isotc211._2005.gmd.CIContactType;
import org.isotc211._2005.gmd.CIResponsiblePartyPropertyType;
import org.isotc211._2005.gmd.EXExtentPropertyType;
import org.isotc211._2005.gmd.EXExtentType;
import org.isotc211._2005.gmd.EXSpatialTemporalExtentType;
import org.isotc211._2005.gmd.EXTemporalExtentPropertyType;
import org.isotc211._2005.gmd.MDDataIdentificationType;
import org.isotc211._2005.gmd.MDKeywordsPropertyType;
import org.isotc211._2005.gmd.MDMetadataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import au.edu.anu.datacommons.external.ExternalMetadataException;
import au.edu.anu.datacommons.external.ExternalMetadataProvider;
import au.edu.anu.datacommons.external.ParamInfo;
import au.edu.anu.datacommons.webservice.bindings.Collection;
import au.edu.anu.datacommons.webservice.bindings.DateCoverage;
import au.edu.anu.datacommons.webservice.bindings.FedoraItem;
/**
* @author Rahul Khanna
*
*/
public class MetadataProviderGmd implements ExternalMetadataProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(MetadataProviderGmd.class);
private static final ClientResponse.Status[] SUCCESS_STATUSES = { ClientResponse.Status.OK };
private static final String FRIENDLY_NAME = "Geographic MetaData extensible markup language (GMD)";
private static final List<ParamInfo> requiredParams = new ArrayList<>(1);
static {
requiredParams.add(new ParamInfo("gmdXmlUrl", "Geographic MetaData URL"));
}
@Autowired
Client client;
@Override
public String getFriendlyName() {
return FRIENDLY_NAME;
}
@Override
public String getFqClassName() {
return this.getClass().getName();
}
@Override
public List<ParamInfo> getRequiredParams() {
return requiredParams;
}
@Override
public FedoraItem retrieveMetadata(MultivaluedMap<String, String> params) throws ExternalMetadataException {
String gmdXmlUrl = getGmdXmlUrl(params);
WebResource webRes = client.resource(gmdXmlUrl);
ClientResponse clientResp = webRes.get(ClientResponse.class);
MDMetadataType resp = null;
if (isSuccess(clientResp.getClientResponseStatus())) {
resp = webRes.get(MDMetadataType.class);
} else {
String entity = clientResp.getEntity(String.class);
throw new ExternalMetadataException(MessageFormat.format("{0} returned unsuccessful HTTP Status: {1}, {2}",
FRIENDLY_NAME, clientResp.getStatus(), entity));
}
return createFedoraItem(resp, gmdXmlUrl);
}
private String getGmdXmlUrl(MultivaluedMap<String, String> params) {
return params.getFirst("gmdXmlUrl");
}
private boolean isSuccess(Status clientResponseStatus) {
for (ClientResponse.Status iStatus : SUCCESS_STATUSES) {
if (iStatus.equals(clientResponseStatus)) {
return true;
}
}
return false;
}
private FedoraItem createFedoraItem(MDMetadataType mdMetadata, String xmlUrl) {
Collection coll = new Collection();
// harcoded value - subtype
coll.setSubType("dataset");
LOGGER.trace("sub type: {}", coll.getSubType());
// url of from where the source XML was downloaded
coll.setWebsiteAddress(xmlUrl);
LOGGER.trace("website url: {}", coll.getWebsiteAddress());
// title -> name
coll.setTitle(getTitle(mdMetadata));
LOGGER.trace("title: {}", coll.getTitle());
// language -> metaLang
coll.setMetadataLanguage(getMetadataLanguage(mdMetadata));
LOGGER.trace("metadata language: {}", coll.getMetadataLanguage());
// fileIdentifier -> externalId
coll.setExtIds(getFileIdentifiers(mdMetadata));
LOGGER.trace("externalId: {}", coll.getExtIds());
// abstract -> briefDesc
coll.setBriefDesc(getAbstract(mdMetadata));
LOGGER.trace("brief description: {}", coll.getBriefDesc());
// timePeriod.beginPosition -> dateFrom
coll.setDateCoverage(getDateCoverage(mdMetadata));
LOGGER.trace("date coverage: {}", coll.getDateCoverage());
// statement -> coverageDateText
coll.setCoverageDateTextList(getCoverageDateTextList(mdMetadata));
LOGGER.trace("coverage date text: {}", coll.getCoverageDateTextList());
// electronicMailAddress -> email
coll.setEmails(getEmails(mdMetadata));
LOGGER.trace("emails: {}", coll.getEmails());
// postalAddress -> postalAddress
coll.setContactAddress(getContactAddress(mdMetadata));
LOGGER.trace("contact address: {}", coll.getContactAddress());
// responsibleParty -> supervisor
coll.setPrincipalInvestigators(getPrincipalInvestigators(mdMetadata));
LOGGER.trace("principal investigators: {}", coll.getPrincipalInvestigators());
// keyword -> locSubject
coll.setKeywords(getKeywords(mdMetadata));
LOGGER.trace("keywords: {}", coll.getKeywords());
return coll;
}
private String getTitle(MDMetadataType mdMetadata) {
try {
CICitationType ciCitation = getDataIdentification(mdMetadata).getCitation().getCICitation();
@SuppressWarnings("unchecked")
JAXBElement<String> characterString = (JAXBElement<String>) ciCitation.getTitle().getCharacterString();
return characterString.getValue();
} catch (Exception e) {
return "";
}
}
private String getMetadataLanguage(MDMetadataType mdMetadata) {
String metadataLang = "";
try {
metadataLang = ((JAXBElement<String>) mdMetadata.getLanguage().getCharacterString()).getValue();
if (metadataLang.equals("eng")) {
metadataLang = "en";
}
} catch (Exception e) {
// no op - empty string
}
return metadataLang;
}
private List<String> getFileIdentifiers(MDMetadataType mdMetadata) {
List<String> fileIdentifiers = new ArrayList<String>();
try {
@SuppressWarnings("unchecked")
JAXBElement<String> fileIdentifierElement = (JAXBElement<String>) mdMetadata.getFileIdentifier()
.getCharacterString();
fileIdentifiers.add(fileIdentifierElement.getValue());
} catch (Exception e) {
// no op - empty list
}
return fileIdentifiers;
}
private String getAbstract(MDMetadataType mdMetadata) {
String briefDesc;
briefDesc = ((JAXBElement<String>) getDataIdentification(mdMetadata).getAbstract().getCharacterString())
.getValue();
return briefDesc;
}
private List<DateCoverage> getDateCoverage(MDMetadataType mdMetadata) {
List<DateCoverage> dateCoverageList = new ArrayList<DateCoverage>();
try {
List<EXExtentPropertyType> extentElements = getDataIdentification(mdMetadata).getExtent();
for (EXExtentPropertyType extentElement : extentElements) {
EXExtentType exExtent = extentElement.getEXExtent();
for (EXTemporalExtentPropertyType temporalExtentPropType : exExtent.getTemporalElement()) {
try {
@SuppressWarnings("unchecked")
JAXBElement<EXSpatialTemporalExtentType> exTemporalExtent = (JAXBElement<EXSpatialTemporalExtentType>) temporalExtentPropType
.getEXTemporalExtent();
} catch (Exception e) {
// no op - continue on to the item
}
}
}
} catch (Exception e) {
// no op - empty list
}
return dateCoverageList;
}
private List<String> getCoverageDateTextList(MDMetadataType mdMetadata) {
List<String> coverageDateTextList = new ArrayList<>();
try {
@SuppressWarnings("unchecked")
JAXBElement<String> statement = (JAXBElement<String>) mdMetadata.getDataQualityInfo().get(0)
.getDQDataQuality().getLineage().getLILineage().getStatement().getCharacterString();
coverageDateTextList.add(statement.getValue());
} catch (Exception e) {
// no op - empty list
}
return coverageDateTextList;
}
private List<String> getEmails(MDMetadataType mdMetadata) {
List<String> emails = new ArrayList<>();
try {
List<CIResponsiblePartyPropertyType> responsibleParties = getDataIdentification(mdMetadata).getCitation()
.getCICitation().getCitedResponsibleParty();
for (CIResponsiblePartyPropertyType party : responsibleParties) {
try {
List<CharacterStringPropertyType> emailElements = party.getCIResponsibleParty().getContactInfo()
.getCIContact().getAddress().getCIAddress().getElectronicMailAddress();
for (CharacterStringPropertyType emailElement : emailElements) {
String email = ((JAXBElement<String>) emailElement.getCharacterString()).getValue();
if (email != null & email.trim().length() > 0 && !emails.contains(email.trim())) {
emails.add(email.trim());
}
}
} catch (Exception e) {
// no op - continue on to next item
}
}
} catch (Exception e) {
// no op - empty list
}
return emails;
}
private String getContactAddress(MDMetadataType mdMetadata) {
StringBuilder contactAddress = new StringBuilder();
try {
CIContactType ciContact = getDataIdentification(mdMetadata).getPointOfContact().get(0)
.getCIResponsibleParty().getContactInfo().getCIContact();
if (ciContact != null) {
// deliveryPoint
for (CharacterStringPropertyType i : ciContact.getAddress().getCIAddress().getDeliveryPoint()) {
@SuppressWarnings("unchecked")
String deliveryPoint = ((JAXBElement<String>) i.getCharacterString()).getValue().trim();
contactAddress.append(deliveryPoint);
contactAddress.append("\r\n");
}
// city
@SuppressWarnings("unchecked")
String city = ((JAXBElement<String>) ciContact.getAddress().getCIAddress().getCity()
.getCharacterString()).getValue().trim();
contactAddress.append(city);
contactAddress.append("\r\n");
// postalCode
@SuppressWarnings("unchecked")
String postalCode = ((JAXBElement<String>) ciContact.getAddress().getCIAddress().getPostalCode()
.getCharacterString()).getValue().trim();
contactAddress.append(postalCode);
contactAddress.append("\r\n");
// country
@SuppressWarnings("unchecked")
String country = ((JAXBElement<String>) ciContact.getAddress().getCIAddress().getCountry()
.getCharacterString()).getValue().trim();
contactAddress.append(country);
contactAddress.append("\r\n");
}
} catch (Exception e) {
// no op - blank string
}
return contactAddress.toString().trim();
}
private List<String> getPrincipalInvestigators(MDMetadataType mdMetadata) {
List<String> investigators = new ArrayList<>();
try {
List<CIResponsiblePartyPropertyType> citedResponsiblePartyList = getDataIdentification(mdMetadata)
.getCitation().getCICitation().getCitedResponsibleParty();
for (CIResponsiblePartyPropertyType i : citedResponsiblePartyList) {
try {
@SuppressWarnings("unchecked")
String value = ((JAXBElement<String>) i.getCIResponsibleParty().getIndividualName()
.getCharacterString()).getValue();
if (value != null && value.trim().length() > 0 && !investigators.contains(value.trim())) {
investigators.add(value);
}
} catch (Exception e) {
// no op - continue on to the next item
}
}
} catch (Exception e) {
// no op - empty list
}
return investigators;
}
private List<String> getKeywords(MDMetadataType mdMetadata) {
List<String> keywords = new ArrayList<>();
try {
List<MDKeywordsPropertyType> descriptiveKeywords = getDataIdentification(mdMetadata)
.getDescriptiveKeywords();
for (MDKeywordsPropertyType i : descriptiveKeywords) {
try {
for (CharacterStringPropertyType j : i.getMDKeywords().getKeyword()) {
String keyword = ((JAXBElement<String>) j.getCharacterString()).getValue();
if (keyword != null && keyword.trim().length() > 0) {
keywords.add(keyword.trim());
}
}
} catch (Exception e) {
// no op - continue on to the next item
}
}
} catch (Exception e) {
// no op - empty list
}
return keywords;
}
@SuppressWarnings("unchecked")
private MDDataIdentificationType getDataIdentification(MDMetadataType mdMetadata) {
return ((JAXBElement<MDDataIdentificationType>) mdMetadata.getIdentificationInfo().get(0)
.getAbstractMDIdentification()).getValue();
}
}