/** * Copyright (C) 2012-2017 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * License version 2 and the aforementioned licenses. * * 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. */ package org.n52.sos.encode; import static org.n52.sos.util.CodingHelper.encoderKeysForElements; import static org.n52.sos.util.CollectionHelper.union; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.namespace.QName; import net.opengis.gml.x32.BaseUnitType; import net.opengis.gml.x32.CodeType; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; import org.isotc211.x2005.gco.CharacterStringPropertyType; import org.isotc211.x2005.gco.CodeListValueType; import org.isotc211.x2005.gco.UnitOfMeasurePropertyType; import org.isotc211.x2005.gmd.CIAddressType; import org.isotc211.x2005.gmd.CICitationType; import org.isotc211.x2005.gmd.CIContactType; import org.isotc211.x2005.gmd.CIDateType; import org.isotc211.x2005.gmd.CIResponsiblePartyDocument; import org.isotc211.x2005.gmd.CIResponsiblePartyPropertyType; import org.isotc211.x2005.gmd.CIResponsiblePartyType; import org.isotc211.x2005.gmd.CIRoleCodePropertyType; import org.isotc211.x2005.gmd.CITelephoneType; import org.isotc211.x2005.gmd.DQConformanceResultType; import org.isotc211.x2005.gmd.DQDomainConsistencyDocument; import org.isotc211.x2005.gmd.DQDomainConsistencyPropertyType; import org.isotc211.x2005.gmd.DQDomainConsistencyType; import org.isotc211.x2005.gmd.DQQuantitativeResultType; import org.isotc211.x2005.gmd.DQResultPropertyType; import org.n52.sos.exception.ows.concrete.UnsupportedEncoderInputException; import org.n52.sos.iso.GcoConstants; import org.n52.sos.iso.gmd.GmdCitationDate; import org.n52.sos.iso.gmd.GmdConformanceResult; import org.n52.sos.iso.gmd.GmdConstants; import org.n52.sos.iso.gmd.GmdDateType; import org.n52.sos.iso.gmd.GmdDomainConsistency; import org.n52.sos.iso.gmd.GmdQuantitativeResult; import org.n52.sos.iso.gmd.GmlBaseUnit; import org.n52.sos.ogc.gml.GmlConstants; import org.n52.sos.ogc.ows.OwsExceptionReport; import org.n52.sos.ogc.sensorML.Role; import org.n52.sos.ogc.sensorML.SmlResponsibleParty; import org.n52.sos.ogc.sos.SosConstants.HelperValues; import org.n52.sos.service.ServiceConstants.SupportedTypeKey; import org.n52.sos.util.CodingHelper; import org.n52.sos.util.XmlHelper; import org.n52.sos.util.XmlOptionsHelper; import org.n52.sos.w3c.SchemaLocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Sets; /** * {@link AbstractXmlEncoder} class to decode ISO TC211 Geographic MetaData * (GMD) extensible markup language. * * @author Carsten Hollmann <c.hollmann@52north.org> * @since 4.2.0 * */ public class Iso19139GmdEncoder extends AbstractXmlEncoder<Object> { private static final Logger LOGGER = LoggerFactory.getLogger(Iso19139GmdEncoder.class); private static final QName QN_GCO_DATE = new QName(GcoConstants.NS_GCO, "Date", GcoConstants.NS_GCO_PREFIX); private static final QName QN_GMD_CONFORMANCE_RESULT = new QName(GmdConstants.NS_GMD, "DQ_ConformanceResult", GmdConstants.NS_GMD_PREFIX); private static final QName QN_GMD_QUANTITATIVE_RESULT = new QName(GmdConstants.NS_GMD, "DQ_QuantitativeResult", GmdConstants.NS_GMD_PREFIX); private static final QName QN_GML_BASE_UNIT = new QName(GmlConstants.NS_GML_32, "BaseUnit", GmlConstants.NS_GML_PREFIX); @SuppressWarnings("unchecked") private static final Set<EncoderKey> ENCODER_KEYS = union( encoderKeysForElements(GmdConstants.NS_GMD, SmlResponsibleParty.class, GmdQuantitativeResult.class, GmdConformanceResult.class), encoderKeysForElements(null, GmdQuantitativeResult.class, GmdConformanceResult.class)); public Iso19139GmdEncoder() { LOGGER.debug("Encoder for the following keys initialized successfully: {}!", Joiner.on(", ") .join(ENCODER_KEYS)); } @Override public Set<EncoderKey> getEncoderKeyType() { return Collections.unmodifiableSet(ENCODER_KEYS); } @Override public Map<SupportedTypeKey, Set<String>> getSupportedTypes() { return Collections.emptyMap(); } @Override public void addNamespacePrefixToMap(final Map<String, String> nameSpacePrefixMap) { nameSpacePrefixMap.put(GmdConstants.NS_GMD, GmdConstants.NS_GMD_PREFIX); } @Override public Set<SchemaLocation> getSchemaLocations() { return Sets.newHashSet(GmdConstants.GMD_SCHEMA_LOCATION); } @Override public XmlObject encode(Object element, Map<HelperValues, String> additionalValues) throws OwsExceptionReport, UnsupportedEncoderInputException { XmlObject encodedObject = null; // try { if (element instanceof SmlResponsibleParty) { encodedObject = encodeResponsibleParty((SmlResponsibleParty) element, additionalValues); } else { if (element instanceof GmdDomainConsistency) { encodedObject = encodeGmdDomainConsistency((GmdDomainConsistency)element, additionalValues); } else { throw new UnsupportedEncoderInputException(this, element); } } // } catch (final XmlException xmle) { // throw new NoApplicableCodeException().causedBy(xmle); // } if (LOGGER.isDebugEnabled() && encodedObject != null) { LOGGER.debug("Encoded object {} is valid: {}", encodedObject.schemaType().toString(), XmlHelper.validateDocument(encodedObject)); } return encodedObject; } private XmlObject encodeResponsibleParty(SmlResponsibleParty responsibleParty, Map<HelperValues, String> additionalValues) throws OwsExceptionReport { CIResponsiblePartyType cirpt = CIResponsiblePartyType.Factory.newInstance(XmlOptionsHelper.getInstance().getXmlOptions()); if (responsibleParty.isSetIndividualName()) { cirpt.addNewIndividualName().setCharacterString(responsibleParty.getIndividualName()); } if (responsibleParty.isSetOrganizationName()) { cirpt.addNewOrganisationName().setCharacterString(responsibleParty.getOrganizationName()); } if (responsibleParty.isSetPositionName()) { cirpt.addNewPositionName().setCharacterString(responsibleParty.getPositionName()); } // set contact encodeContact(cirpt.addNewContactInfo().addNewCIContact(), responsibleParty); // set role encodeRole(cirpt.addNewRole(), responsibleParty.getRoleObject()); if (additionalValues.containsKey(HelperValues.PROPERTY_TYPE)) { CIResponsiblePartyPropertyType cirppt = CIResponsiblePartyPropertyType.Factory.newInstance(XmlOptionsHelper.getInstance().getXmlOptions()); cirppt.setCIResponsibleParty(cirpt); return cirppt; } else if (additionalValues.containsKey(HelperValues.DOCUMENT)) { CIResponsiblePartyDocument cirpd = CIResponsiblePartyDocument.Factory.newInstance(XmlOptionsHelper.getInstance().getXmlOptions()); cirpd.setCIResponsibleParty(cirpt); } return cirpt; } private void encodeContact(CIContactType cic, SmlResponsibleParty responsibleParty) { if (responsibleParty.isSetAddress()) { encodeCiAddress(cic.addNewAddress().addNewCIAddress(), responsibleParty); } if (responsibleParty.isSetContactInstructions()) { cic.addNewContactInstructions().setCharacterString(responsibleParty.getContactInstructions()); } if (responsibleParty.isSetHoursOfService()) { cic.addNewHoursOfService().setCharacterString(responsibleParty.getHoursOfService()); } if (responsibleParty.isSetOnlineResources()) { cic.addNewOnlineResource().setHref(responsibleParty.getOnlineResources().get(0)); } if (responsibleParty.isSetPhone()) { encodePhone(cic.addNewPhone().addNewCITelephone(), responsibleParty); } } private void encodeCiAddress(CIAddressType ciat, SmlResponsibleParty responsibleParty) { if (responsibleParty.isSetAdministrativeArea()) { ciat.addNewAdministrativeArea().setCharacterString(responsibleParty.getAdministrativeArea()); } if (responsibleParty.isSetCity()) { ciat.addNewCity().setCharacterString(responsibleParty.getCity()); } if (responsibleParty.isSetCountry()) { ciat.addNewCountry().setCharacterString(responsibleParty.getCountry()); } if (responsibleParty.isSetPostalCode()) { ciat.addNewPostalCode().setCharacterString(responsibleParty.getPostalCode()); } if (responsibleParty.isSetDeliveryPoint()) { ciat.setDeliveryPointArray(listToCharacterStringPropertyTypeArray(responsibleParty.getDeliveryPoint())); } if (responsibleParty.isSetEmail()) { ciat.setElectronicMailAddressArray(listToCharacterStringPropertyTypeArray(Lists .newArrayList(responsibleParty.getEmail()))); } } private void encodePhone(CITelephoneType citt, SmlResponsibleParty responsibleParty) { if (responsibleParty.isSetPhoneVoice()) { citt.setVoiceArray(listToCharacterStringPropertyTypeArray(responsibleParty.getPhoneVoice())); } if (responsibleParty.isSetPhoneFax()) { citt.setFacsimileArray(listToCharacterStringPropertyTypeArray(responsibleParty.getPhoneFax())); } } private void encodeRole(CIRoleCodePropertyType circpt, Role role) throws OwsExceptionReport { XmlObject encodeObjectToXml = CodingHelper.encodeObjectToXml(GcoConstants.NS_GCO, role); if (encodeObjectToXml != null) { circpt.addNewCIRoleCode().set(encodeObjectToXml); } } private XmlObject encodeGmdDomainConsistency(GmdDomainConsistency element, Map<HelperValues, String> additionalValues) throws OwsExceptionReport { if (additionalValues.containsKey(HelperValues.DOCUMENT)) { DQDomainConsistencyDocument document = DQDomainConsistencyDocument.Factory.newInstance(getXmlOptions()); DQResultPropertyType addNewResult = document.addNewDQDomainConsistency().addNewResult(); encodeGmdDomainConsistency(addNewResult, (GmdDomainConsistency) element); return document; } else if (additionalValues.containsKey(HelperValues.PROPERTY_TYPE)) { DQDomainConsistencyPropertyType propertyType = DQDomainConsistencyPropertyType.Factory.newInstance(getXmlOptions()); DQResultPropertyType addNewResult = propertyType.addNewDQDomainConsistency().addNewResult(); encodeGmdDomainConsistency(addNewResult, (GmdDomainConsistency) element); return propertyType; } else { DQDomainConsistencyType type = DQDomainConsistencyType.Factory.newInstance(getXmlOptions()); DQResultPropertyType addNewResult = type.addNewResult(); encodeGmdDomainConsistency(addNewResult, (GmdDomainConsistency) element); return type; } } private void encodeGmdDomainConsistency(DQResultPropertyType xbResult, GmdDomainConsistency domainConsistency) throws OwsExceptionReport { if (domainConsistency instanceof GmdConformanceResult) { encodeGmdConformanceResult(xbResult, (GmdConformanceResult) domainConsistency); } else if (domainConsistency instanceof GmdQuantitativeResult) { encodeGmdQuantitativeResult(xbResult, (GmdQuantitativeResult) domainConsistency); } else { throw new UnsupportedEncoderInputException(this, domainConsistency); } } private void encodeGmdConformanceResult(DQResultPropertyType xbResult, GmdConformanceResult gmdConformanceResult) { DQConformanceResultType dqConformanceResultType = (DQConformanceResultType) xbResult.addNewAbstractDQResult().substitute(QN_GMD_CONFORMANCE_RESULT, DQConformanceResultType.type); if (gmdConformanceResult.isSetPassNilReason()) { dqConformanceResultType.addNewPass().setNilReason(gmdConformanceResult.getPassNilReason().name()); } else { dqConformanceResultType.addNewPass().setBoolean(gmdConformanceResult.isPass()); } dqConformanceResultType.addNewExplanation().setCharacterString( gmdConformanceResult.getSpecification().getExplanation()); CICitationType xbCitation = dqConformanceResultType.addNewSpecification().addNewCICitation(); xbCitation.addNewTitle().setCharacterString(gmdConformanceResult.getSpecification().getCitation().getTitle()); CIDateType xbCiDate = xbCitation.addNewDate().addNewCIDate(); CodeListValueType xbCIDateTypeCode = xbCiDate.addNewDateType().addNewCIDateTypeCode(); GmdCitationDate gmdCitationDate = gmdConformanceResult.getSpecification().getCitation().getDate(); GmdDateType gmdDateType = gmdCitationDate.getDateType(); xbCIDateTypeCode.setCodeList(gmdDateType.getCodeList()); xbCIDateTypeCode.setCodeListValue(gmdDateType.getCodeListValue()); if (gmdDateType.getCodeSpace() != null && !gmdDateType.getCodeSpace().isEmpty()) { xbCIDateTypeCode.setCodeSpace(gmdDateType.getCodeSpace()); } xbCIDateTypeCode.setStringValue(gmdDateType.getValue()); XmlCursor newCursor = xbCiDate.addNewDate().newCursor(); newCursor.toNextToken(); newCursor.beginElement(QN_GCO_DATE); newCursor.insertChars(gmdCitationDate.getDate()); newCursor.dispose(); } private void encodeGmdQuantitativeResult(DQResultPropertyType xbResult, GmdQuantitativeResult gmdQuantitativeResult) { DQQuantitativeResultType dqQuantitativeResultType = (DQQuantitativeResultType) xbResult.addNewAbstractDQResult().substitute(QN_GMD_QUANTITATIVE_RESULT, DQQuantitativeResultType.type); GmlBaseUnit unit = gmdQuantitativeResult.getUnit(); UnitOfMeasurePropertyType valueUnit = dqQuantitativeResultType.addNewValueUnit(); BaseUnitType xbBaseUnit = (BaseUnitType) valueUnit.addNewUnitDefinition().substitute(QN_GML_BASE_UNIT, BaseUnitType.type); CodeType xbCatalogSymbol = xbBaseUnit.addNewCatalogSymbol(); xbCatalogSymbol.setCodeSpace(unit.getCatalogSymbol().getCodeSpace()); xbCatalogSymbol.setStringValue(unit.getCatalogSymbol().getValue()); xbBaseUnit.setId(unit.getId()); xbBaseUnit.addNewUnitsSystem().setHref(unit.getUnitSystem()); xbBaseUnit.addNewIdentifier().setCodeSpace(unit.getIdentifier()); if (gmdQuantitativeResult.isSetValueNilReason()) { dqQuantitativeResultType.addNewValue().setNilReason(gmdQuantitativeResult.getValueNilReason().name()); } else { XmlCursor cursor = dqQuantitativeResultType.addNewValue().addNewRecord().newCursor(); cursor.toNextToken(); cursor.insertChars(gmdQuantitativeResult.getValue()); cursor.dispose(); } } private CharacterStringPropertyType[] listToCharacterStringPropertyTypeArray(List<String> list) { List<CharacterStringPropertyType> values = Lists.newArrayList(); for (String string : list) { CharacterStringPropertyType cspt = CharacterStringPropertyType.Factory.newInstance(); cspt.setCharacterString(string); values.add(cspt); } return values.toArray(new CharacterStringPropertyType[0]); } private static XmlOptions getXmlOptions() { return XmlOptionsHelper.getInstance().getXmlOptions(); } }