org.n52.oxf.sos.adapter.v200.SOSCapabilitiesMapper_200.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.oxf.sos.adapter.v200.SOSCapabilitiesMapper_200.java

Source

/**
 * Copyright (C) 2012-2014 52North 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 publishedby 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.oxf.sos.adapter.v200;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import net.opengis.fes.x20.ComparisonOperatorType;
import net.opengis.fes.x20.ComparisonOperatorsType;
import net.opengis.fes.x20.FilterCapabilitiesDocument.FilterCapabilities;
import net.opengis.fes.x20.ScalarCapabilitiesType;
import net.opengis.fes.x20.SpatialCapabilitiesType;
import net.opengis.fes.x20.TemporalCapabilitiesType;
import net.opengis.gml.x32.CodeType;
import net.opengis.gml.x32.EnvelopeDocument;
import net.opengis.gml.x32.EnvelopeType;
import net.opengis.gml.x32.TimePeriodType;
import net.opengis.ows.x11.AllowedValuesDocument.AllowedValues;
import net.opengis.ows.x11.ContactType;
import net.opengis.ows.x11.DCPDocument;
import net.opengis.ows.x11.DomainType;
import net.opengis.ows.x11.LanguageStringType;
import net.opengis.ows.x11.OperationDocument;
import net.opengis.ows.x11.RequestMethodType;
import net.opengis.ows.x11.ResponsiblePartySubsetType;
import net.opengis.ows.x11.ValueType;
import net.opengis.sos.x20.CapabilitiesDocument;
import net.opengis.sos.x20.CapabilitiesType;
import net.opengis.sos.x20.CapabilitiesType.Contents;
import net.opengis.sos.x20.ContentsType;
import net.opengis.sos.x20.ObservationOfferingDocument;
import net.opengis.sos.x20.ObservationOfferingType;
import net.opengis.sos.x20.ObservationOfferingType.ResultTime;
import net.opengis.swes.x20.AbstractContentsType.Offering;
import net.opengis.swes.x20.AbstractOfferingType.RelatedFeature;

import org.apache.commons.lang.ArrayUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.xmlbeans.XmlException;
import org.n52.oxf.OXFException;
import org.n52.oxf.ows.Constraint;
import org.n52.oxf.ows.ServiceDescriptor;
import org.n52.oxf.ows.capabilities.Contact;
import org.n52.oxf.ows.capabilities.DCP;
import org.n52.oxf.ows.capabilities.DatasetParameter;
import org.n52.oxf.ows.capabilities.GetRequestMethod;
import org.n52.oxf.ows.capabilities.IBoundingBox;
import org.n52.oxf.ows.capabilities.IDiscreteValueDomain;
import org.n52.oxf.ows.capabilities.ITime;
import org.n52.oxf.ows.capabilities.OnlineResource;
import org.n52.oxf.ows.capabilities.Operation;
import org.n52.oxf.ows.capabilities.OperationsMetadata;
import org.n52.oxf.ows.capabilities.Parameter;
import org.n52.oxf.ows.capabilities.PostRequestMethod;
import org.n52.oxf.ows.capabilities.RequestMethod;
import org.n52.oxf.ows.capabilities.ServiceContact;
import org.n52.oxf.ows.capabilities.ServiceIdentification;
import org.n52.oxf.ows.capabilities.ServiceProvider;
import org.n52.oxf.sos.capabilities.ObservationOffering;
import org.n52.oxf.sos.capabilities.SOSContents;
import org.n52.oxf.util.web.HttpClient;
import org.n52.oxf.util.web.HttpClientException;
import org.n52.oxf.util.web.SimpleHttpClient;
import org.n52.oxf.valueDomains.StringValueDomain;
import org.n52.oxf.valueDomains.filter.ComparisonFilter;
import org.n52.oxf.valueDomains.filter.FilterValueDomain;
import org.n52.oxf.valueDomains.filter.IFilter;
import org.n52.oxf.valueDomains.spatial.BoundingBox;
import org.n52.oxf.valueDomains.time.TemporalValueDomain;
import org.n52.oxf.valueDomains.time.TimePeriod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SOSCapabilitiesMapper_200 {

    private static final Logger LOGGER = LoggerFactory.getLogger(SOSCapabilitiesMapper_200.class);

    public ServiceDescriptor mapCapabilities(final CapabilitiesDocument capabilitiesDoc) throws OXFException {

        final String version = mapVersion(capabilitiesDoc);
        final CapabilitiesType capabilities = capabilitiesDoc.getCapabilities();
        final ServiceProvider serviceProvider = mapServiceProvider(capabilities);
        final OperationsMetadata operationsMetadata = mapOperationsMetadata(capabilities);
        final ServiceIdentification serviceIdentification = mapServiceIdentification(capabilities);
        // OperationsMetadata operationsMetadata = null;
        final SOSContents contents = mapContents(capabilitiesDoc);

        // addDatasetParameterFromContentsSection(operationsMetadata, contents);

        final ServiceDescriptor serviceDesc = new ServiceDescriptor(version, serviceIdentification, serviceProvider,
                operationsMetadata, contents);
        return serviceDesc;
    }

    private void addDatasetParameterFromContentsSection(final OperationsMetadata operationsMetadata,
            final SOSContents contents) {
        final Operation getObservationOp = operationsMetadata.getOperationByName("GetObservation");

        for (int i = 0; i < contents.getDataIdentificationCount(); i++) {
            final ObservationOffering obsOff = contents.getDataIdentification(i);

            //
            // --- id:
            //
            final StringValueDomain idDomain = new StringValueDomain(obsOff.getIdentifier());
            final DatasetParameter idParam = new DatasetParameter("id", false, idDomain, obsOff,
                    Parameter.COMMON_NAME_RESOURCE_ID);
            getObservationOp.addParameter(idParam);

            //
            // --- bbox:
            //
            final IBoundingBox[] bboxDomain = obsOff.getBoundingBoxes();
            for (final IBoundingBox bbox : bboxDomain) {
                final DatasetParameter bboxParam = new DatasetParameter("bbox", false, bbox, obsOff,
                        Parameter.COMMON_NAME_BBOX);
                getObservationOp.addParameter(bboxParam);
            }

            //
            // --- srs:
            //
            if (obsOff.getAvailableCRSs() != null) {
                final StringValueDomain srsDomain = new StringValueDomain(obsOff.getAvailableCRSs());
                final DatasetParameter srsParam = new DatasetParameter("srs", false, srsDomain, obsOff,
                        Parameter.COMMON_NAME_SRS);
                getObservationOp.addParameter(srsParam);
            }

            //
            // --- time:
            //
            final IDiscreteValueDomain<ITime> temporalDomain = obsOff.getTemporalDomain();
            final DatasetParameter eventTimeParam = new DatasetParameter("eventTime", false, temporalDomain, obsOff,
                    Parameter.COMMON_NAME_TIME);
            getObservationOp.addParameter(eventTimeParam);
        }
    }

    private OperationsMetadata mapOperationsMetadata(final CapabilitiesType capabilities) {

        if (!capabilities.isSetOperationsMetadata()) {
            return null;
        }
        final net.opengis.ows.x11.OperationsMetadataDocument.OperationsMetadata operationsMetadata = capabilities
                .getOperationsMetadata();
        //
        // map the operations:
        //
        final OperationDocument.Operation[] xbOperations = operationsMetadata.getOperationArray();
        final Operation[] ocOperations = new Operation[xbOperations.length];
        for (int i = 0; i < xbOperations.length; i++) {
            final OperationDocument.Operation xbOperation = xbOperations[i];
            final String ocOperationName = xbOperation.getName();
            //
            // map the operations DCPs:
            //
            final DCPDocument.DCP[] xbDcps = xbOperation.getDCPArray();
            final DCP[] ocDcps = new DCP[xbDcps.length];
            for (int j = 0; j < xbDcps.length; j++) {
                final DCPDocument.DCP xbDcp = xbDcps[j];
                //
                // map the RequestMethods:
                //
                final List<RequestMethod> ocRequestMethods = new ArrayList<RequestMethod>();

                final RequestMethodType[] xbGetRequestMethods = xbDcp.getHTTP().getGetArray();
                for (final RequestMethodType xbGetRequestMethod : xbGetRequestMethods) {
                    final OnlineResource ocOnlineRessource = new OnlineResource(xbGetRequestMethod.getHref());
                    final RequestMethod ocRequestMethod = new GetRequestMethod(ocOnlineRessource);
                    addConstraints(xbGetRequestMethod, ocRequestMethod);
                    ocRequestMethods.add(ocRequestMethod);
                }
                final RequestMethodType[] xbPostRequestMethods = xbDcp.getHTTP().getPostArray();
                for (final RequestMethodType xbPostRequestMethod : xbPostRequestMethods) {
                    final OnlineResource ocOnlineRessource = new OnlineResource(xbPostRequestMethod.getHref());
                    final RequestMethod ocRequestMethod = new PostRequestMethod(ocOnlineRessource);
                    addConstraints(xbPostRequestMethod, ocRequestMethod);
                    ocRequestMethods.add(ocRequestMethod);
                }

                ocDcps[j] = new DCP(ocRequestMethods);
            }
            //
            // map the operations parameters:
            //
            final DomainType[] xbParameters = xbOperation.getParameterArray();
            final List<Parameter> ocParameters = new ArrayList<Parameter>();
            for (final DomainType xbParameter : xbParameters) {
                final String parameterName = xbParameter.getName();
                if (!parameterName.equalsIgnoreCase("eventTime")) {
                    //
                    // map the parameters' values to StringValueDomains
                    //
                    final AllowedValues xbAllowedValues = xbParameter.getAllowedValues();
                    if (xbAllowedValues != null) {
                        final ValueType[] xbValues = xbAllowedValues.getValueArray();
                        final StringValueDomain ocValues = new StringValueDomain();
                        for (final ValueType xbValue : xbValues) {
                            ocValues.addPossibleValue(xbValue.getStringValue());
                        }
                        final Parameter ocParameter = new Parameter(parameterName, true, ocValues, null);
                        ocParameters.add(ocParameter);
                    }
                }
            }
            final Parameter[] parametersArray = new Parameter[ocParameters.size()];
            ocParameters.toArray(parametersArray);
            ocOperations[i] = new Operation(ocOperationName, parametersArray, null, ocDcps);
        }
        return new OperationsMetadata(ocOperations);
    }

    private void addConstraints(final RequestMethodType xbGetRequestMethod, final RequestMethod ocRequestMethod) {
        if (xbGetRequestMethod.getConstraintArray() != null) {
            for (final DomainType xbConstraint : xbGetRequestMethod.getConstraintArray()) {
                final String name = xbConstraint.getName();
                final ArrayList<String> allowedValues = new ArrayList<String>();
                if (xbConstraint.isSetAllowedValues()) {
                    for (final ValueType xbAllowedValue : xbConstraint.getAllowedValues().getValueArray()) {
                        allowedValues.add(xbAllowedValue.getStringValue());
                    }
                }
                if (name != null && !name.isEmpty() && !allowedValues.isEmpty()) {
                    ocRequestMethod.addOwsConstraint(
                            new Constraint(name, allowedValues.toArray(new String[allowedValues.size()])));
                }
            }
        }
    }

    public static void main(final String[] args) {
        try {
            final HttpClient client = new SimpleHttpClient();
            final String request = "http://sensorweb.demo.52north.org/52nSOSv3_200/sos?REQUEST=GetCapabilities&SERVICE=SOS";

            final HttpResponse response = client.executeGet(request);
            final HttpEntity responseEntity = response.getEntity();
            final InputStream responseStream = responseEntity.getContent();
            new SOSCapabilitiesMapper_200().mapCapabilities(CapabilitiesDocument.Factory.parse(responseStream));
        } catch (final HttpClientException e) {
            LOGGER.error("Exception thrown: {}", e.getMessage(), e);
        } catch (final IOException e) {
            LOGGER.error("Exception thrown: {}", e.getMessage(), e);
        } catch (final XmlException e) {
            LOGGER.error("Exception thrown: {}", e.getMessage(), e);
        } catch (final OXFException e) {
            LOGGER.error("Exception thrown: {}", e.getMessage(), e);
        }
    }

    private SOSContents mapContents(final CapabilitiesDocument capabilitiesDoc) throws OXFException {
        final CapabilitiesType capabilities = capabilitiesDoc.getCapabilities();
        final Contents xb_contents = capabilities.getContents();
        final ContentsType contentsType = xb_contents.getContents();
        final String[] observablePropertys = contentsType.getObservablePropertyArray();
        final String[] responseFormats = contentsType.getResponseFormatArray();
        final Offering[] xb_obsOfferings = contentsType.getOfferingArray();
        final ArrayList<ObservationOffering> oc_obsOffList = new ArrayList<ObservationOffering>();
        for (final Offering xb_obsOffering2 : xb_obsOfferings) {
            ObservationOfferingDocument xb_obsOfferingDoc = null;
            try {
                xb_obsOfferingDoc = ObservationOfferingDocument.Factory.parse(xb_obsOffering2.newInputStream());
            } catch (final XmlException e) {
                throw new OXFException("Could not parse DOM node.", e);
            } catch (final IOException e) {
                throw new OXFException("Could not parse DOM node.", e);
            }
            final ObservationOfferingType xb_obsOffering = xb_obsOfferingDoc.getObservationOffering();

            if (!xb_obsOffering.isSetObservedArea()) {
                continue; // does not contain any observations/features
            }

            IBoundingBox[] oc_bbox = null;
            String[] oc_availabaleCRSs = null;
            EnvelopeDocument envelopeDoc = null;
            try {
                envelopeDoc = EnvelopeDocument.Factory.parse(xb_obsOffering.getObservedArea().newInputStream());
            } catch (final IOException e) {
                throw new OXFException("Could not get DOM node.", e);
            } catch (final XmlException e) {
                throw new OXFException("Could not get DOM node.", e);
            }

            final EnvelopeType envelope = envelopeDoc.getEnvelope();
            if (envelope != null) {
                // availableCRSs:
                final String oc_crs = envelope.getSrsName();
                if (oc_crs != null) {
                    oc_availabaleCRSs = new String[] { oc_crs };
                }
                //                else {
                // TODO Think about throwing an exception because of one missing attribute because this
                // situation can occur often when a new offering is set up and no data is available. Set
                // it null and then it's okay! (ehjuerrens@52north.org)
                // throw new
                // NullPointerException("SRS not specified in the Capabilities' 'gml:Envelope'-tag.");
                //                }

                // BoundingBox:
                oc_bbox = new IBoundingBox[1];
                final List<?> xb_lowerCornerList = envelope.getLowerCorner().getListValue();
                final double[] oc_lowerCornerList = new double[xb_lowerCornerList.size()];

                final List<?> xb_upperCornerList = envelope.getUpperCorner().getListValue();
                final double[] oc_upperCornerList = new double[xb_upperCornerList.size()];

                for (int j = 0; j < xb_lowerCornerList.size(); j++) {
                    oc_lowerCornerList[j] = (Double) xb_lowerCornerList.get(j);
                }
                for (int j = 0; j < xb_upperCornerList.size(); j++) {
                    oc_upperCornerList[j] = (Double) xb_upperCornerList.get(j);
                }

                oc_bbox[0] = new BoundingBox(oc_crs, oc_lowerCornerList, oc_upperCornerList);
            }

            // result:
            final RelatedFeature[] oc_foiIDs = xb_obsOffering.getRelatedFeatureArray();
            final String[] oc_relatedFeatures = new String[oc_foiIDs.length];
            for (int j = 0; j < oc_foiIDs.length; j++) {
                // FIXME this is 52n SOS 2.0 specific
                oc_relatedFeatures[j] = oc_foiIDs[j].getFeatureRelationship().getTarget().getHref();
            }

            // TODO: these variables should also be initialized
            final String oc_pointOfContact = null;
            final Locale[] oc_language = null;
            final String[] oc_keywords = null;
            final String oc_abstractDescription = null;

            final ObservationOffering oc_obsOff = new ObservationOffering(getTitle(xb_obsOffering),
                    xb_obsOffering.getIdentifier(), oc_bbox,
                    (String[]) ArrayUtils.addAll(responseFormats, xb_obsOffering.getResponseFormatArray()),
                    oc_availabaleCRSs, capabilities.getServiceIdentification().getFees(), oc_language,
                    oc_pointOfContact, getTemporalDomain(xb_obsOffering), oc_abstractDescription, oc_keywords,
                    new String[] { xb_obsOffering.getProcedure() }, oc_relatedFeatures,
                    (String[]) ArrayUtils.addAll(xb_obsOffering.getObservablePropertyArray(), observablePropertys),
                    null, // not supported in SOS 2.0
                    xb_obsOffering.getResponseFormatArray(), getFilterDomain(capabilities));

            oc_obsOffList.add(oc_obsOff);
        }

        return new SOSContents(oc_obsOffList);
    }

    private IDiscreteValueDomain<ITime> getTemporalDomain(final ObservationOfferingType xb_obsOffering) {
        // TemporalDomain:
        final List<ITime> oc_timeList = new ArrayList<ITime>();
        final ResultTime resultTime = xb_obsOffering.getResultTime();
        if (resultTime != null && resultTime.getTimePeriod() != null) {
            final TimePeriodType xb_timePeriod = resultTime.getTimePeriod();
            final String beginPos = xb_timePeriod.getBeginPosition().getStringValue();
            final String endPos = xb_timePeriod.getEndPosition().getStringValue();
            if (!beginPos.equals("") && !endPos.equals("")) {
                final TimePeriod oc_timePeriod = new TimePeriod(beginPos, endPos);
                oc_timeList.add(oc_timePeriod);
            }
        }
        return new TemporalValueDomain(oc_timeList);
    }

    private FilterValueDomain getFilterDomain(final CapabilitiesType capabilities) {
        final FilterValueDomain filterDomain = new FilterValueDomain();
        if (capabilities.getFilterCapabilities() != null) {
            final FilterCapabilities filterCaps = capabilities.getFilterCapabilities().getFilterCapabilities();
            if (filterCaps != null) {
                processScalarFilterCapabilities(filterDomain, filterCaps.getScalarCapabilities());
                processSpatialFilterCapabilities(filterDomain, filterCaps.getSpatialCapabilities());
                processTemporalFilterCapabilities(filterDomain, filterCaps.getTemporalCapabilities());
            }
        }
        return filterDomain;
    }

    private String getTitle(final ObservationOfferingType xb_obsOffering) {
        // title (take the first name or if name does not exist take the id)
        final CodeType[] xb_names = xb_obsOffering.getNameArray();
        String oc_title;
        if (xb_names != null && xb_names.length > 0 && xb_names[0].getStringValue() != null) {
            oc_title = xb_names[0].getStringValue();
        } else {
            oc_title = xb_obsOffering.getIdentifier();
        }
        return oc_title;
    }

    private void processScalarFilterCapabilities(final FilterValueDomain filterDomain,
            final ScalarCapabilitiesType scalarCapabilities) {
        if (scalarCapabilities != null) {
            final ComparisonOperatorsType comparisonOperators = scalarCapabilities.getComparisonOperators();
            if (comparisonOperators != null) {
                final ComparisonOperatorType[] xb_compOpsArray = comparisonOperators.getComparisonOperatorArray();
                for (final ComparisonOperatorType compOp : xb_compOpsArray) {
                    if (compOp.equals(ComparisonOperatorType.EQUAL)) {
                        final IFilter filter = new ComparisonFilter(ComparisonFilter.PROPERTY_IS_EQUAL_TO);
                        filterDomain.addPossibleValue(filter);
                    } else if (compOp.equals(ComparisonOperatorType.GREATER_THAN)) {
                        final IFilter filter = new ComparisonFilter(ComparisonFilter.PROPERTY_IS_GREATER_THAN);
                        filterDomain.addPossibleValue(filter);
                    } else if (compOp.equals(ComparisonOperatorType.LESS_THAN)) {
                        final IFilter filter = new ComparisonFilter(ComparisonFilter.PROPERTY_IS_LESS_THAN);
                        filterDomain.addPossibleValue(filter);
                    } else if (compOp.equals(ComparisonOperatorType.NOT_EQUAL)) {
                        final IFilter filter = new ComparisonFilter(ComparisonFilter.PROPERTY_IS_NOT_EQUAL_TO);
                        filterDomain.addPossibleValue(filter);
                    }
                }
            }
        }
    }

    private void processSpatialFilterCapabilities(final FilterValueDomain filterDomain,
            final SpatialCapabilitiesType spatialCapabilities) {
        //        if (spatialCapabilities != null) {
        // TODO implement
        // throw new NotImplementedException();
        //        }
    }

    private void processTemporalFilterCapabilities(final FilterValueDomain filterDomain,
            final TemporalCapabilitiesType temporalCapabilities) {
        //        if (temporalCapabilities != null) {
        // TODO implement
        // throw new NotImplementedException();
        //        }

    }

    private ServiceIdentification mapServiceIdentification(final CapabilitiesType capabilities) {

        if (!capabilities.isSetServiceIdentification()) {
            return null;
        }

        final net.opengis.ows.x11.ServiceIdentificationDocument.ServiceIdentification serviceIdentification = capabilities
                .getServiceIdentification();

        final String oc_title = serviceIdentification.getTitleArray(0).getStringValue();
        final String oc_serviceType = serviceIdentification.getServiceType().getStringValue();
        final String[] oc_serviceTypeVersions = serviceIdentification.getServiceTypeVersionArray();

        final String oc_fees = serviceIdentification.getFees();
        final String[] oc_accessConstraints = serviceIdentification.getAccessConstraintsArray();
        String oc_abstract = null;
        if (serviceIdentification.getAbstractArray() != null) {
            oc_abstract = serviceIdentification.getAbstractArray(0).getStringValue();
        }
        String[] oc_keywords = null;

        final List<String> oc_keywordsVec = new ArrayList<String>();
        for (int i = 0; i < serviceIdentification.getKeywordsArray().length; i++) {
            final LanguageStringType[] xb_keywords = serviceIdentification.getKeywordsArray(i).getKeywordArray();
            for (final LanguageStringType xb_keyword : xb_keywords) {
                oc_keywordsVec.add(xb_keyword.getStringValue());
            }
        }
        oc_keywords = new String[oc_keywordsVec.size()];
        oc_keywordsVec.toArray(oc_keywords);

        return new ServiceIdentification(oc_title, oc_serviceType, oc_serviceTypeVersions, oc_fees,
                oc_accessConstraints, oc_abstract, oc_keywords);
    }

    private String mapVersion(final CapabilitiesDocument capsDoc) {
        return capsDoc.getCapabilities().getVersion();
    }

    private static ServiceProvider mapServiceProvider(final CapabilitiesType capabilities) {
        if (!capabilities.isSetServiceProvider()) {
            return null;
        }
        final net.opengis.ows.x11.ServiceProviderDocument.ServiceProvider serviceProvider = capabilities
                .getServiceProvider();
        final String name = serviceProvider.getProviderName();
        final ResponsiblePartySubsetType contact = serviceProvider.getServiceContact();

        final String individualName = contact.getIndividualName();
        final String organisationName = null;
        final String positionName = contact.getPositionName();
        final ContactType contactInfo = contact.getContactInfo(); // TODO parse info
        final Contact info = new Contact(null, null, null, null, null, null);
        final ServiceContact serviceContact = new ServiceContact(individualName, organisationName, positionName,
                info);

        return new ServiceProvider(name, serviceContact);
    }

}