/**
* 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.sos.v1;
import java.util.Collection;
import java.util.Set;
import javax.xml.namespace.QName;
import net.opengis.ogc.ComparisonOperatorType;
import net.opengis.ogc.ComparisonOperatorsType;
import net.opengis.ogc.GeometryOperandsType;
import net.opengis.ogc.IdCapabilitiesType;
import net.opengis.ogc.ScalarCapabilitiesType;
import net.opengis.ogc.SpatialCapabilitiesType;
import net.opengis.ogc.SpatialOperatorNameType;
import net.opengis.ogc.SpatialOperatorType;
import net.opengis.ogc.SpatialOperatorsType;
import net.opengis.ogc.TemporalCapabilitiesType;
import net.opengis.ogc.TemporalOperandsType;
import net.opengis.ogc.TemporalOperatorNameType;
import net.opengis.ogc.TemporalOperatorType;
import net.opengis.ogc.TemporalOperatorsType;
import net.opengis.sos.x10.CapabilitiesDocument;
import net.opengis.sos.x10.CapabilitiesDocument.Capabilities;
import net.opengis.sos.x10.ContentsDocument.Contents;
import net.opengis.sos.x10.ContentsDocument.Contents.ObservationOfferingList;
import net.opengis.sos.x10.FilterCapabilitiesDocument.FilterCapabilities;
import net.opengis.sos.x10.ObservationOfferingType;
import org.apache.xmlbeans.XmlObject;
import org.n52.oxf.xml.NcNameResolver;
import org.n52.sos.encode.Encoder;
import org.n52.sos.exception.ows.NoApplicableCodeException;
import org.n52.sos.ogc.filter.FilterConstants.ComparisonOperator;
import org.n52.sos.ogc.filter.FilterConstants.SpatialOperator;
import org.n52.sos.ogc.filter.FilterConstants.TimeOperator;
import org.n52.sos.ogc.gml.CodeType;
import org.n52.sos.ogc.gml.GmlConstants;
import org.n52.sos.ogc.gml.time.TimePeriod;
import org.n52.sos.ogc.ows.OWSConstants;
import org.n52.sos.ogc.ows.OwsExceptionReport;
import org.n52.sos.ogc.sos.Sos1Constants;
import org.n52.sos.ogc.sos.SosCapabilities;
import org.n52.sos.ogc.sos.SosConstants;
import org.n52.sos.ogc.sos.SosEnvelope;
import org.n52.sos.ogc.sos.SosObservationOffering;
import org.n52.sos.ogc.swe.SweConstants;
import org.n52.sos.response.GetCapabilitiesResponse;
import org.n52.sos.util.CodingHelper;
import org.n52.sos.util.CollectionHelper;
import org.n52.sos.util.N52XmlHelper;
import org.n52.sos.util.XmlOptionsHelper;
import org.n52.sos.w3c.SchemaLocation;
import com.google.common.collect.Sets;
/**
* @since 4.0.0
*
*/
public class GetCapabilitiesResponseEncoder extends AbstractSosResponseEncoder<GetCapabilitiesResponse> {
public GetCapabilitiesResponseEncoder() {
super(SosConstants.Operations.GetCapabilities.name(), GetCapabilitiesResponse.class);
}
@Override
protected Set<SchemaLocation> getConcreteSchemaLocations() {
return Sets.newHashSet(Sos1Constants.GET_CAPABILITIES_SOS1_SCHEMA_LOCATION);
}
@Override
protected XmlObject create(GetCapabilitiesResponse response) throws OwsExceptionReport {
CapabilitiesDocument xbCapsDoc =
CapabilitiesDocument.Factory.newInstance(XmlOptionsHelper.getInstance().getXmlOptions());
// cursor for getting prefixes
Capabilities xbCaps = xbCapsDoc.addNewCapabilities();
// set version.
xbCaps.setVersion(response.getVersion());
SosCapabilities sosCapabilities = response.getCapabilities();
if (sosCapabilities.isSetServiceIdentification()) {
xbCaps.addNewServiceIdentification().set(
CodingHelper.encodeObjectToXml(OWSConstants.NS_OWS, sosCapabilities.getServiceIdentification()));
}
if (sosCapabilities.isSetServiceProvider()) {
xbCaps.addNewServiceProvider().set(
CodingHelper.encodeObjectToXml(OWSConstants.NS_OWS, sosCapabilities.getServiceProvider()));
}
if (sosCapabilities.isSetOperationsMetadata()) {
xbCaps.addNewOperationsMetadata().set(
CodingHelper.encodeObjectToXml(OWSConstants.NS_OWS, sosCapabilities.getOperationsMetadata()));
}
if (sosCapabilities.isSetFilterCapabilities()) {
setFilterCapabilities(xbCaps.addNewFilterCapabilities(), sosCapabilities.getFilterCapabilities());
}
if (sosCapabilities.isSetContents()) {
setContents(xbCaps.addNewContents(), sosCapabilities.getContents(), response.getVersion());
}
N52XmlHelper.setSchemaLocationsToDocument(xbCapsDoc,
Sets.newHashSet(N52XmlHelper.getSchemaLocationForSOS100()));
return xbCapsDoc;
}
/**
* Sets the FilterCapabilities section to the capabilities document.
*
* @param filterCapabilities
*
* @param sosFilterCaps
* FilterCapabilities.
*/
protected void setFilterCapabilities(FilterCapabilities filterCapabilities,
org.n52.sos.ogc.filter.FilterCapabilities sosFilterCaps) {
setScalarFilterCapabilities(filterCapabilities.addNewScalarCapabilities(), sosFilterCaps);
setSpatialFilterCapabilities(filterCapabilities.addNewSpatialCapabilities(), sosFilterCaps);
setTemporalFilterCapabilities(filterCapabilities.addNewTemporalCapabilities(), sosFilterCaps);
setIdFilterCapabilities(filterCapabilities.addNewIdCapabilities());
}
/**
* Sets the content section to the Capabilities document.
*
* @param xbContents
* SOS 2.0 contents section
* @param offerings
* SOS offerings for contents
* @param version
* SOS response version
*
*
* @throws OwsExceptionReport
* * if an error occurs.
*/
protected void setContents(Contents xbContents, Collection<SosObservationOffering> offerings, String version)
throws OwsExceptionReport {
// Contents xbContType = xbContents.addNewContents();
ObservationOfferingList xbObservationOfferings = xbContents.addNewObservationOfferingList();
for (SosObservationOffering offering : offerings) {
ObservationOfferingType xbObservationOffering = xbObservationOfferings.addNewObservationOffering();
// TODO check NAme or ID
xbObservationOffering.setId(NcNameResolver.fixNcName(offering.getOffering().getIdentifier()));
xbObservationOffering.addNewName().set(CodingHelper.encodeObjectToXml(GmlConstants.NS_GML,
new CodeType(offering.getOffering().getIdentifier(), "uniqueID")));
// only if fois are contained for the offering set the values of the
// envelope
Encoder<XmlObject, SosEnvelope> encoder =
CodingHelper.getEncoder(GmlConstants.NS_GML, offering.getObservedArea());
xbObservationOffering.addNewBoundedBy().addNewEnvelope().set(encoder.encode(offering.getObservedArea()));
// TODO: add intended application
// xbObservationOffering.addIntendedApplication("");
// set gml:name to offering's id (not ncname resolved)
for (CodeType name : offering.getOffering().getName()) {
xbObservationOffering.addNewName().set(CodingHelper.encodeObjectToXml(GmlConstants.NS_GML, name));
}
/*
* // set up phenomena Collection<String> phenomenons =
* offering.getObservableProperties(); Collection<String>
* compositePhenomena = offering.getCompositePhenomena();
* Collection<String> componentsOfCompPhens = new
* ArrayList<String>();
*
* // set up composite phenomena if (compositePhenomena != null) {
* first add a new compositePhenomenon for every compositePhenomenon
* for (String compositePhenomenon : compositePhenomena) {
* Collection<String> components =
* offering.getPhens4CompPhens().get(compositePhenomenon);
* componentsOfCompPhens.addAll(components); if (components != null)
* { PhenomenonPropertyType xb_opType =
* xb_oo.addNewObservedProperty();
* xb_opType.set(SosConfigurator.getInstance().getOmEncoder()
* .createCompositePhenomenon(compositePhenomenon, components)); } }
* }
*/
// set observableProperties [0..*]
for (String phenomenon : offering.getObservableProperties()) {
xbObservationOffering.addNewObservedProperty().setHref(phenomenon);
}
// set up time
if (offering.getPhenomenonTime() instanceof TimePeriod) {
XmlObject encodeObject =
CodingHelper.encodeObjectToXml(SweConstants.NS_SWE_101, offering.getPhenomenonTime());
xbObservationOffering.addNewTime().set(encodeObject);
}
// add feature of interests
if (offering.isSetFeatureOfInterestTypes()) {
for (String featureOfInterestType : offering.getFeatureOfInterestTypes()) {
xbObservationOffering.addNewFeatureOfInterest().setHref(featureOfInterestType);
}
}
// set procedures
if (offering.isSetProcedureDescriptionFormats()) {
for (String procedureDescriptionFormat : offering.getProcedureDescriptionFormats()) {
xbObservationOffering.addNewProcedure().setHref(procedureDescriptionFormat);
}
}
for (String procedure : offering.getProcedures()) {
xbObservationOffering.addNewProcedure().setHref(procedure);
}
for (String featureOfInterest : offering.getFeatureOfInterest()) {
xbObservationOffering.addNewFeatureOfInterest().setHref(featureOfInterest);
}
// insert result models
Collection<QName> resultModels = offering.getResultModels();
if (CollectionHelper.isEmpty(resultModels)) {
throw new NoApplicableCodeException()
.withMessage(
"No result models are contained in the database for the offering: %s! Please contact the admin of this SOS.",
offering);
}
/*
* for (QName resultModelQName : resultModels) { XmlQName
* xbResultModel = xb_oo.addNewResultModel();
* xbResultModel.setStringValue(rmString.getPrefix() + ":" +
* rmString.getLocalPart());
* xbResultModel.set(Sos1Constants.RESULT_MODEL_MEASUREMENT);
* xbResultModel.setStringValue("om:Measurement"); QName qName = new
* QName(rmString.getPrefix(), rmString.getLocalPart());
* xbResultModel.setQNameValue(resultModelQName); // TODO: Change if
* XmlBeans-Bug is fixed // String value = cursor.getTextValue(); //
* cursor.setTextValue(value.replaceFirst("ns", //
* OMConstants.NS_OM_PREFIX)); }
*/
// set responseFormat [0..*]
if (offering.isSetResponseFormats()) {
for (String responseFormat : offering.getResponseFormats()) {
xbObservationOffering.addNewResponseFormat().setStringValue(responseFormat);
}
}
// set response Mode
for (String responseMode : offering.getResponseModes()) {
xbObservationOffering.addNewResponseMode().setStringValue(responseMode);
}
}
}
/**
* Set the IdFilterCapabilities.
*
* !!! Modify method addicted to your implementation !!!
*
* @param idCapabilities
* IdCapabilities.
*/
protected void setIdFilterCapabilities(IdCapabilitiesType idCapabilities) {
idCapabilities.addNewFID();
idCapabilities.addNewEID();
}
/**
* Sets the SpatialFilterCapabilities.
*
* !!! Modify method addicted to your implementation !!!
*
* @param spatialCapabilities
* SpatialCapabilities.
* @param sosFilterCaps
*/
protected void setSpatialFilterCapabilities(SpatialCapabilitiesType spatialCapabilities,
org.n52.sos.ogc.filter.FilterCapabilities sosFilterCaps) {
// set GeometryOperands
if (!sosFilterCaps.getSpatialOperands().isEmpty()) {
GeometryOperandsType spatialOperands = spatialCapabilities.addNewGeometryOperands();
for (QName operand : sosFilterCaps.getSpatialOperands()) {
spatialOperands.addGeometryOperand(operand);
}
}
// set SpatialOperators
if (!sosFilterCaps.getSpatialOperators().isEmpty()) {
SpatialOperatorsType spatialOps = spatialCapabilities.addNewSpatialOperators();
Set<SpatialOperator> keys = sosFilterCaps.getSpatialOperators().keySet();
for (SpatialOperator spatialOperator : keys) {
SpatialOperatorType operator = spatialOps.addNewSpatialOperator();
operator.setName(getEnum4SpatialOperator(spatialOperator));
GeometryOperandsType bboxGeomOps = operator.addNewGeometryOperands();
for (QName operand : sosFilterCaps.getSpatialOperators().get(spatialOperator)) {
bboxGeomOps.addGeometryOperand(operand);
}
}
}
}
/**
* Sets the TemporalFilterCapabilities.
*
* !!! Modify method addicted to your implementation !!!
*
* @param temporalCapabilities
* TemporalCapabilities.
* @param sosFilterCaps
*/
protected void setTemporalFilterCapabilities(TemporalCapabilitiesType temporalCapabilities,
org.n52.sos.ogc.filter.FilterCapabilities sosFilterCaps) {
// set TemporalOperands
if (!sosFilterCaps.getTemporalOperands().isEmpty()) {
TemporalOperandsType tempOperands = temporalCapabilities.addNewTemporalOperands();
for (QName operand : sosFilterCaps.getTemporalOperands()) {
tempOperands.addTemporalOperand(operand);
}
}
// set TemporalOperators
if (!sosFilterCaps.getTempporalOperators().isEmpty()) {
TemporalOperatorsType temporalOps = temporalCapabilities.addNewTemporalOperators();
Set<TimeOperator> keys = sosFilterCaps.getTempporalOperators().keySet();
for (TimeOperator temporalOperator : keys) {
TemporalOperatorType operator = temporalOps.addNewTemporalOperator();
operator.setName(getEnum4TemporalOperator(temporalOperator));
TemporalOperandsType bboxGeomOps = operator.addNewTemporalOperands();
for (QName operand : sosFilterCaps.getTempporalOperators().get(temporalOperator)) {
bboxGeomOps.addTemporalOperand(operand);
}
}
}
}
/**
* Sets the ScalarFilterCapabilities.
*
* !!! Modify method addicted to your implementation !!!
*
* @param scalarCapabilities
* ScalarCapabilities.
* @param sosFilterCaps
*/
protected void setScalarFilterCapabilities(ScalarCapabilitiesType scalarCapabilities,
org.n52.sos.ogc.filter.FilterCapabilities sosFilterCaps) {
if (!sosFilterCaps.getComparisonOperators().isEmpty()) {
ComparisonOperatorsType scalarOps = scalarCapabilities.addNewComparisonOperators();
for (ComparisonOperator operator : sosFilterCaps.getComparisonOperators()) {
scalarOps.addComparisonOperator(getEnum4ComparisonOperator(operator));
}
}
}
/**
* Get the Enum for the spatial operator.
*
* @param spatialOperator
* Supported spatial operator
* @return Enum
*/
protected net.opengis.ogc.SpatialOperatorNameType.Enum getEnum4SpatialOperator(SpatialOperator spatialOperator) {
switch (spatialOperator) {
case BBOX:
return SpatialOperatorNameType.BBOX;
case Beyond:
return SpatialOperatorNameType.BEYOND;
case Contains:
return SpatialOperatorNameType.CONTAINS;
case Crosses:
return SpatialOperatorNameType.CROSSES;
case Disjoint:
return SpatialOperatorNameType.DISJOINT;
case DWithin:
return SpatialOperatorNameType.D_WITHIN;
case Equals:
return SpatialOperatorNameType.EQUALS;
case Intersects:
return SpatialOperatorNameType.INTERSECTS;
case Overlaps:
return SpatialOperatorNameType.OVERLAPS;
case Touches:
return SpatialOperatorNameType.TOUCHES;
case Within:
return SpatialOperatorNameType.WITHIN;
default:
return null;
}
}
/**
* Get the Enum for the temporal operator.
*
* @param temporalOperator
* Supported temporal operator
* @return Enum
*/
protected net.opengis.ogc.TemporalOperatorNameType.Enum getEnum4TemporalOperator(TimeOperator temporalOperator) {
switch (temporalOperator) {
case TM_After:
return TemporalOperatorNameType.TM_AFTER;
case TM_Before:
return TemporalOperatorNameType.TM_BEFORE;
case TM_Begins:
return TemporalOperatorNameType.TM_BEGINS;
case TM_BegunBy:
return TemporalOperatorNameType.TM_BEGUN_BY;
case TM_Contains:
return TemporalOperatorNameType.TM_CONTAINS;
case TM_During:
return TemporalOperatorNameType.TM_DURING;
case TM_EndedBy:
return TemporalOperatorNameType.TM_ENDED_BY;
case TM_Ends:
return TemporalOperatorNameType.TM_ENDS;
case TM_Equals:
return TemporalOperatorNameType.TM_EQUALS;
case TM_Meets:
return TemporalOperatorNameType.TM_MEETS;
case TM_MetBy:
return TemporalOperatorNameType.TM_MET_BY;
case TM_OverlappedBy:
return TemporalOperatorNameType.TM_OVERLAPPED_BY;
case TM_Overlaps:
return TemporalOperatorNameType.TM_OVERLAPS;
default:
return null;
}
}
/**
* Get the Enum for the comparison operator.
*
* @param comparisonOperator
* Supported comparison operator
* @return Enum
*/
protected net.opengis.ogc.ComparisonOperatorType.Enum getEnum4ComparisonOperator(
ComparisonOperator comparisonOperator) {
switch (comparisonOperator) {
case PropertyIsBetween:
return ComparisonOperatorType.BETWEEN;
case PropertyIsEqualTo:
return ComparisonOperatorType.EQUAL_TO;
case PropertyIsGreaterThan:
return ComparisonOperatorType.GREATER_THAN;
case PropertyIsGreaterThanOrEqualTo:
return ComparisonOperatorType.GREATER_THAN_EQUAL_TO;
case PropertyIsLessThan:
return ComparisonOperatorType.LESS_THAN;
case PropertyIsLessThanOrEqualTo:
return ComparisonOperatorType.LESS_THAN_EQUAL_TO;
case PropertyIsLike:
return ComparisonOperatorType.LIKE;
case PropertyIsNotEqualTo:
return ComparisonOperatorType.NOT_EQUAL_TO;
case PropertyIsNull:
return ComparisonOperatorType.NULL_CHECK;
default:
return null;
}
}
}