/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.sos.ws.rs; import org.constellation.ServiceDef; import org.constellation.ServiceDef.Specification; import org.constellation.sos.configuration.SOSConfigurer; import org.constellation.sos.ws.SOSworker; import org.constellation.ws.CstlServiceException; import org.constellation.ws.MimeType; import org.constellation.ws.ServiceConfigurer; import org.constellation.ws.UnauthorizedException; import org.constellation.ws.Worker; import org.constellation.ws.rs.OGCWebService; import org.geotoolkit.ows.xml.AcceptFormats; import org.geotoolkit.ows.xml.AcceptVersions; import org.geotoolkit.ows.xml.OWSXmlFactory; import org.geotoolkit.ows.xml.RequestBase; import org.geotoolkit.ows.xml.Sections; import org.geotoolkit.ows.xml.v110.ExceptionReport; import org.geotoolkit.ows.xml.v110.SectionsType; import org.geotoolkit.sos.xml.GetCapabilities; import org.geotoolkit.sos.xml.GetFeatureOfInterest; import org.geotoolkit.sos.xml.GetObservation; import org.geotoolkit.sos.xml.GetObservationById; import org.geotoolkit.sos.xml.GetResult; import org.geotoolkit.sos.xml.GetResultTemplate; import org.geotoolkit.sos.xml.InsertObservation; import org.geotoolkit.sos.xml.InsertResult; import org.geotoolkit.sos.xml.InsertResultTemplate; import org.geotoolkit.sos.xml.ResponseModeType; import org.geotoolkit.sos.xml.SOSMarshallerPool; import org.geotoolkit.sos.xml.SOSResponseWrapper; import org.geotoolkit.sos.xml.GetFeatureOfInterestTime; import org.geotoolkit.swes.xml.DeleteSensor; import org.geotoolkit.swes.xml.DescribeSensor; import org.geotoolkit.swes.xml.InsertSensor; import org.geotoolkit.util.StringUtilities; import org.opengis.filter.Filter; import org.opengis.filter.spatial.BBOX; import org.opengis.observation.ObservationCollection; import org.opengis.temporal.Instant; import org.opengis.temporal.Period; import javax.inject.Singleton; import javax.ws.rs.Path; import javax.ws.rs.core.Response; import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; import java.util.logging.Level; import static org.constellation.api.QueryConstants.ACCEPT_FORMATS_PARAMETER; import static org.constellation.api.QueryConstants.ACCEPT_VERSIONS_PARAMETER; import static org.constellation.api.QueryConstants.REQUEST_PARAMETER; import static org.constellation.api.QueryConstants.SECTIONS_PARAMETER; import static org.constellation.api.QueryConstants.SERVICE_PARAMETER; import static org.constellation.api.QueryConstants.UPDATESEQUENCE_PARAMETER; import static org.constellation.api.QueryConstants.VERSION_PARAMETER; import static org.constellation.sos.ws.SOSConstants.ACCEPTED_OUTPUT_FORMATS; import static org.constellation.sos.ws.SOSConstants.FEATURE_OF_INTEREST; import static org.constellation.sos.ws.SOSConstants.OBSERVATION; import static org.constellation.sos.ws.SOSConstants.OBSERVATION_ID; import static org.constellation.sos.ws.SOSConstants.OBSERVED_PROPERTY; import static org.constellation.sos.ws.SOSConstants.OFFERING; import static org.constellation.sos.ws.SOSConstants.OM_NAMESPACE; import static org.constellation.sos.ws.SOSConstants.OUTPUT_FORMAT; import static org.constellation.sos.ws.SOSConstants.PROCEDURE; import static org.constellation.sos.ws.SOSConstants.PROCEDURE_DESCRIPTION_FORMAT; import static org.constellation.sos.ws.SOSConstants.RESPONSE_FORMAT; import static org.constellation.sos.ws.SOSConstants.RESPONSE_FORMAT_V200; import static org.constellation.sos.ws.SOSConstants.RESPONSE_MODE; import static org.constellation.sos.ws.SOSConstants.RESULT_MODEL; import static org.constellation.sos.ws.SOSConstants.SRS_NAME; import org.constellation.sos.ws.SOSUtils; import static org.geotoolkit.ows.xml.OWSExceptionCode.INVALID_PARAMETER_VALUE; import static org.geotoolkit.ows.xml.OWSExceptionCode.MISSING_PARAMETER_VALUE; import static org.geotoolkit.ows.xml.OWSExceptionCode.OPERATION_NOT_SUPPORTED; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildAcceptVersion; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildBBOX; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildDeleteSensor; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildDescribeSensor; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildGetCapabilities; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildGetFeatureOfInterest; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildGetObservation; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildGetObservationById; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildGetResult; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildGetResultTemplate; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildTimeDuring; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildTimeEquals; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildTimeInstant; import static org.geotoolkit.sos.xml.SOSXmlFactory.buildTimePeriod; // Jersey dependencies //JAXB dependencies // Constellation dependencies // Geotoolkit dependencies /** * * @author Guilhem Legal * @author Benjamin Garcia (Geomatys) * * @version 0.9 */ @Path("sos/{serviceId}") @Singleton public class SOService extends OGCWebService<SOSworker> { /** * Build a new Restfull SOS service. */ public SOService() throws CstlServiceException { super(Specification.SOS); setXMLContext(SOSMarshallerPool.getInstance()); LOGGER.log(Level.INFO, "SOS REST service running ({0} instances)", getWorkerMapSize()); } /** * {@inheritDoc} */ @Override protected Class getWorkerClass() { return SOSworker.class; } /** * {@inheritDoc} */ @Override protected Class<? extends ServiceConfigurer> getConfigurerClass() { return SOSConfigurer.class; } /** * {@inheritDoc} */ @Override public Response treatIncomingRequest(final Object objectRequest, final SOSworker worker) { ServiceDef serviceDef = null; try { final RequestBase request; if (objectRequest == null) { request = adaptQuery(getParameter(REQUEST_PARAMETER, true), worker); } else if (objectRequest instanceof RequestBase) { request = (RequestBase) objectRequest; } else { throw new CstlServiceException("The operation " + objectRequest.getClass().getName() + " is not supported by the service", INVALID_PARAMETER_VALUE, "request"); } serviceDef = worker.getVersionFromNumber(request.getVersion()); final String currentVersion; if (request.getVersion() != null) { currentVersion = request.getVersion().toString(); } else { currentVersion = null; } if (request instanceof GetObservation) { final GetObservation go = (GetObservation) request; final Object response = worker.getObservation(go); String outputFormat = go.getResponseFormat(); if (outputFormat != null) { if (outputFormat.startsWith(MimeType.TEXT_XML) || outputFormat.equals(RESPONSE_FORMAT_V200)) { outputFormat = MimeType.TEXT_XML; } else if (outputFormat.startsWith(MimeType.TEXT_PLAIN)) { outputFormat = MimeType.TEXT_PLAIN; } else if (outputFormat.startsWith(MimeType.APP_JSON)) { outputFormat = MimeType.APP_JSON; } } final Object marshalled; if (response instanceof ObservationCollection) { marshalled = new SOSResponseWrapper(response, currentVersion); } else { marshalled = response; } return Response.ok(marshalled, outputFormat).build(); } if (request instanceof GetObservationById) { final GetObservationById go = (GetObservationById)request; String outputFormat = go.getResponseFormat(); if (outputFormat != null) { if (outputFormat.startsWith(MimeType.TEXT_XML) || outputFormat.equals(RESPONSE_FORMAT_V200)) { outputFormat = MimeType.TEXT_XML; } else if (outputFormat.startsWith(MimeType.TEXT_PLAIN)) { outputFormat = MimeType.TEXT_PLAIN; } else if (outputFormat.startsWith(MimeType.APP_JSON)) { outputFormat = MimeType.APP_JSON; } } else { outputFormat = MimeType.TEXT_XML; } return Response.ok(worker.getObservationById(go), outputFormat).build(); } if (request instanceof DescribeSensor) { final DescribeSensor ds = (DescribeSensor)request; return Response.ok(worker.describeSensor(ds), MimeType.TEXT_XML).build(); } if (request instanceof GetFeatureOfInterest) { final GetFeatureOfInterest gf = (GetFeatureOfInterest)request; final SOSResponseWrapper response = new SOSResponseWrapper(worker.getFeatureOfInterest(gf), currentVersion); final String outputFormat = gf.getResponseFormat(); return Response.ok(response, outputFormat).build(); } if (request instanceof InsertObservation) { final InsertObservation is = (InsertObservation)request; final String outputFormat = is.getResponseFormat(); return Response.ok(worker.insertObservation(is), outputFormat).build(); } if (request instanceof GetResult) { final GetResult gr = (GetResult)request; final String outputFormat = gr.getResponseFormat(); return Response.ok(worker.getResult(gr), outputFormat).build(); } if (request instanceof InsertSensor) { final InsertSensor rs = (InsertSensor)request; return Response.ok(worker.registerSensor(rs), MimeType.TEXT_XML).build(); } if (request instanceof DeleteSensor) { final DeleteSensor rs = (DeleteSensor)request; return Response.ok(worker.deleteSensor(rs), MimeType.TEXT_XML).build(); } if (request instanceof InsertResult) { final InsertResult rs = (InsertResult)request; final String outputFormat = rs.getResponseFormat(); return Response.ok(worker.insertResult(rs), outputFormat).build(); } if (request instanceof InsertResultTemplate) { final InsertResultTemplate rs = (InsertResultTemplate)request; final String outputFormat = rs.getResponseFormat(); return Response.ok(worker.insertResultTemplate(rs), outputFormat).build(); } if (request instanceof GetResultTemplate) { final GetResultTemplate rs = (GetResultTemplate)request; final String outputFormat = rs.getResponseFormat(); return Response.ok(worker.getResultTemplate(rs), outputFormat).build(); } if (request instanceof GetFeatureOfInterestTime) { final GetFeatureOfInterestTime gft = (GetFeatureOfInterestTime)request; final SOSResponseWrapper response = new SOSResponseWrapper(worker.getFeatureOfInterestTime(gft), currentVersion); return Response.ok(response, MimeType.TEXT_XML).build(); } if (request instanceof GetCapabilities) { final GetCapabilities gc = (GetCapabilities)request; return Response.ok(worker.getCapabilities(gc), getCapabilitiesOutputFormat(gc)).build(); } throw new CstlServiceException("The operation " + request + " is not supported by the service", INVALID_PARAMETER_VALUE, "request"); } catch (CstlServiceException ex) { return processExceptionResponse(ex, serviceDef, worker); } } /** * Throw an CstlServiceException when a request is not available in GET. * * @param operationName The name of the request. (example getCapabilities) * * @throws CstlServiceException every time. */ private void throwUnsupportedGetMethod(String operationName) throws CstlServiceException { throw new CstlServiceException("The operation " + operationName + " is only requestable in XML via POST method", OPERATION_NOT_SUPPORTED, operationName); } /** * {@inheritDoc} */ @Override protected Response processExceptionResponse(final CstlServiceException ex, ServiceDef serviceDef, final Worker w) { // asking for authentication if (ex instanceof UnauthorizedException) { return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", " Basic").build(); } logException(ex); final String exceptionVersion; if (serviceDef == null) { if (w != null) { exceptionVersion = w.getBestVersion(null).exceptionVersion.toString(); } else { exceptionVersion = null; } } else { exceptionVersion = serviceDef.exceptionVersion.toString(); } final String exceptionCode = getOWSExceptionCodeRepresentation(ex.getExceptionCode()); final ExceptionReport report = new ExceptionReport(ex.getMessage(), exceptionCode, ex.getLocator(), exceptionVersion); return Response.ok(report, MimeType.TEXT_XML).build(); } /** * Build request object from KVP parameters. * * @param request * @return * @throws CstlServiceException */ private RequestBase adaptQuery(String request, final Worker w) throws CstlServiceException { if ("InsertObservation" .equalsIgnoreCase(request) || "RegisterSensor" .equalsIgnoreCase(request) ){ throwUnsupportedGetMethod(request); } else if ("GetFeatureOfInterest".equalsIgnoreCase(request)) { return createGetFeatureOfInterest(w); } else if ("GetFeatureOfInterestTime".equalsIgnoreCase(request)) { return createGetFeatureOfInterestTime(w); } else if ("GetObservation".equalsIgnoreCase(request)) { return createGetObservation(w); } else if ("GetResult".equalsIgnoreCase(request)) { return createGetResult(w); } else if ("DescribeSensor".equalsIgnoreCase(request)) { return createDescribeSensor(w); } else if ("DeleteSensor".equalsIgnoreCase(request)) { return createDeleteSensor(w); } else if ("GetResultTemplate".equalsIgnoreCase(request)) { return createGetResultTemplate(w); } else if ("GetObservationById".equalsIgnoreCase(request)) { return createGetObservationById(w); } else if ("GetCapabilities".equalsIgnoreCase(request)) { return createNewGetCapabilities(w); } throw new CstlServiceException("The operation " + request + " is not supported by the service", INVALID_PARAMETER_VALUE, "request"); } /** * Build a new getCapabilities request from kvp encoding */ private GetCapabilities createNewGetCapabilities(final Worker worker) throws CstlServiceException { String version = getParameter(ACCEPT_VERSIONS_PARAMETER, false); String currentVersion = getParameter(VERSION_PARAMETER, false); if (currentVersion == null) { currentVersion = worker.getBestVersion(null).version.toString(); } worker.checkVersionSupported(currentVersion, true); final List<String> versions = new ArrayList<>(); if (version != null) { String[] vArray = version.split(","); versions.addAll(Arrays.asList(vArray)); } else { versions.add(currentVersion); } final AcceptVersions acceptVersions = buildAcceptVersion(currentVersion, versions); final String format = getParameter(ACCEPT_FORMATS_PARAMETER, false); final AcceptFormats formats; if (format != null) { formats = OWSXmlFactory.buildAcceptFormat("1.1.0", Arrays.asList(format)); } else { formats = null; } final String updateSequence = getParameter(UPDATESEQUENCE_PARAMETER, false); //We transform the String of sections in a list. //In the same time we verify that the requested sections are valid. final String section = getParameter(SECTIONS_PARAMETER, false); List<String> requestedSections = new ArrayList<>(); if (section != null && !section.equalsIgnoreCase("All")) { final StringTokenizer tokens = new StringTokenizer(section, ",;"); while (tokens.hasMoreTokens()) { final String token = tokens.nextToken().trim(); if (SectionsType.getExistingSections("1.1.1").contains(token)){ requestedSections.add(token); } else { throw new CstlServiceException("The section " + token + " does not exist", INVALID_PARAMETER_VALUE, "Sections"); } } } else { //if there is no requested Sections we add all the sections requestedSections = SectionsType.getExistingSections("1.1.1"); } final Sections sections = OWSXmlFactory.buildSections("1.1.0", requestedSections); return buildGetCapabilities(currentVersion, acceptVersions, sections, formats, updateSequence, getParameter(SERVICE_PARAMETER, true)); } private String getCapabilitiesOutputFormat(final GetCapabilities request) { final AcceptFormats formats = request.getAcceptFormats(); if (formats != null && formats.getOutputFormat().size() > 0 ) { for (String form: formats.getOutputFormat()) { if (ACCEPTED_OUTPUT_FORMATS.contains(form)) { return form; } } } return MimeType.APPLICATION_XML; } /** * Build a new getCapabilities request from kvp encoding */ private DescribeSensor createDescribeSensor(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); final String procedure = getParameter(PROCEDURE, true); if (procedure.isEmpty()) { throw new CstlServiceException("The parameter procedure must be specified", MISSING_PARAMETER_VALUE, "procedure"); } final String varName; if (currentVersion.equals("1.0.0")) { varName = OUTPUT_FORMAT; } else { varName = PROCEDURE_DESCRIPTION_FORMAT; } final String outputFormat = getParameter(varName, true); if (outputFormat.isEmpty()) { throw new CstlServiceException("The parameter " + varName + " must be specified", MISSING_PARAMETER_VALUE, varName); } return buildDescribeSensor(currentVersion, service, procedure, outputFormat); } private GetFeatureOfInterest createGetFeatureOfInterest(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); if (currentVersion.equals("1.0.0")) { final String featureID = getParameter("FeatureOfInterestId", true); final List<String> fidList = StringUtilities.toStringList(featureID); return buildGetFeatureOfInterest(getParameter(VERSION_PARAMETER, true),getParameter(SERVICE_PARAMETER, true), fidList); } else { final String obpList = getParameter(OBSERVED_PROPERTY, false); final List<String> observedProperties; if (obpList != null) { observedProperties = StringUtilities.toStringList(obpList); } else { observedProperties = new ArrayList<>(); } final String prList = getParameter(PROCEDURE, false); final List<String> procedures; if (prList != null) { procedures = StringUtilities.toStringList(prList); } else { procedures = new ArrayList<>(); } final String foList = getParameter(FEATURE_OF_INTEREST, false); final List<String> foids; if (foList != null) { foids = StringUtilities.toStringList(foList); } else { foids = new ArrayList<>(); } final String bboxStr = getParameter("spatialFilter", false); final Filter spatialFilter; if (bboxStr != null) { spatialFilter = parseBBoxFilter(bboxStr); } else { spatialFilter = null; } final Object extension = getParameter("extension", false); final List<Object> extensions = new ArrayList<>(); if (extension != null) { extensions.add(extension); } return buildGetFeatureOfInterest(currentVersion, service, foids, observedProperties, procedures, spatialFilter, extensions); } } private GetFeatureOfInterestTime createGetFeatureOfInterestTime(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); if (currentVersion.equals("1.0.0")) { return new org.geotoolkit.sos.xml.v100.GetFeatureOfInterestTime(getParameter(VERSION_PARAMETER, true), getParameter("FeatureOfInterestId", true)); } else { throw new CstlServiceException("The operation GetFeatureOfInterestTime is only requestable in 1.0.0 version", OPERATION_NOT_SUPPORTED, "GetFeatureOfInterestTime"); } } private DeleteSensor createDeleteSensor(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); final String procedure = getParameter(PROCEDURE, true); if (procedure.isEmpty()) { throw new CstlServiceException("The parameter procedure must be specified", MISSING_PARAMETER_VALUE, "procedure"); } return buildDeleteSensor(currentVersion, service, procedure); } private GetResult createGetResult(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); if (currentVersion.equals("2.0.0")) { final String offering = getParameter(OFFERING, true); if (offering.isEmpty()) { throw new CstlServiceException("The parameter offering must be specified", MISSING_PARAMETER_VALUE, OFFERING); } final String observedProperty = getParameter(OBSERVED_PROPERTY, true); if (observedProperty.isEmpty()) { throw new CstlServiceException("The parameter observedProperty must be specified", MISSING_PARAMETER_VALUE, OBSERVED_PROPERTY); } final String foList = getParameter(FEATURE_OF_INTEREST, false); final List<String> foids; if (foList != null) { foids = StringUtilities.toStringList(foList); } else { foids = new ArrayList<>(); } final String bboxStr = getParameter("spatialFilter", false); final Filter spatialFilter; if (bboxStr != null) { spatialFilter = parseBBoxFilter(bboxStr); } else { spatialFilter = null; } final String tempStr = getParameter("temporalFilter", false); final List<Filter> temporalFilters = new ArrayList<>(); if (tempStr != null) { temporalFilters.add(parseTemporalFilter(tempStr)); } final Object extension = getParameter("extension", false); final List<Object> extensions = new ArrayList<>(); if (extension != null) { extensions.add(extension); } return buildGetResult(currentVersion, service, offering, observedProperty, foids, spatialFilter, temporalFilters, extensions); } else { throwUnsupportedGetMethod("GetResult"); return null; } } private GetResultTemplate createGetResultTemplate(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); final String offering = getParameter(OFFERING, true); if (offering.isEmpty()) { throw new CstlServiceException("The parameter offering must be specified", MISSING_PARAMETER_VALUE, OFFERING); } final String observedProperty = getParameter(OBSERVED_PROPERTY, true); if (observedProperty.isEmpty()) { throw new CstlServiceException("The parameter observedProperty must be specified", MISSING_PARAMETER_VALUE, OBSERVED_PROPERTY); } final Object extension = getParameter("extension", false); final List<Object> extensions = new ArrayList<>(); if (extension != null) { extensions.add(extension); } return buildGetResultTemplate(currentVersion, service, offering, observedProperty, extensions); } private GetObservationById createGetObservationById(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); final List<String> observations; final String srsName; final QName resultModel; final ResponseModeType responseMode; final String responseFormat; final List<Object> extensions = new ArrayList<>(); if (currentVersion.equals("2.0.0")) { final String observationList = getParameter(OBSERVATION, true); if (observationList.isEmpty()) { throw new CstlServiceException("The parameter observation must be specified", MISSING_PARAMETER_VALUE, OBSERVATION); } else { observations = StringUtilities.toStringList(observationList); } srsName = null; resultModel = null; responseMode = null; responseFormat = null; final Object extension = getParameter("extension", false); if (extension != null) { extensions.add(extension); } } else { final String observationList = getParameter(OBSERVATION_ID, true); if (observationList.isEmpty()) { throw new CstlServiceException("The parameter observationID must be specified", MISSING_PARAMETER_VALUE, OBSERVATION_ID); } else { observations = StringUtilities.toStringList(observationList); } srsName = getParameter(SRS_NAME, false); responseFormat = getParameter(RESPONSE_FORMAT, true); final String rm = getParameter(RESULT_MODEL, false); if (rm != null && rm.indexOf(':') != -1) { resultModel = new QName(OM_NAMESPACE, rm.substring(rm.indexOf(':'))); } else if (rm != null){ resultModel = new QName(rm); } else { resultModel = null; } final String rmd = getParameter(RESPONSE_MODE, false); if (rmd != null) { responseMode = ResponseModeType.fromValue(rm); } else { responseMode = null; } } return buildGetObservationById(currentVersion, service, observations, resultModel, responseMode, srsName, responseFormat, extensions); } private GetObservation createGetObservation(final Worker worker) throws CstlServiceException { final String service = getParameter(SERVICE_PARAMETER, true); if (service.isEmpty()) { throw new CstlServiceException("The parameter service must be specified", MISSING_PARAMETER_VALUE, "service"); } else if (!"SOS".equals(service)) { throw new CstlServiceException("The parameter service value must be \"SOS\"", INVALID_PARAMETER_VALUE, "service"); } final String currentVersion = getParameter(VERSION_PARAMETER, true); if (currentVersion.isEmpty()) { throw new CstlServiceException("The parameter version must be specified", MISSING_PARAMETER_VALUE, "version"); } worker.checkVersionSupported(currentVersion, false); if (currentVersion.equals("2.0.0")) { final String offList = getParameter(OFFERING, false); final List<String> offering; if (offList != null) { offering = StringUtilities.toStringList(offList); } else { offering = new ArrayList<>(); } final String obpList = getParameter(OBSERVED_PROPERTY, false); final List<String> observedProperties; if (obpList != null) { observedProperties = StringUtilities.toStringList(obpList); } else { observedProperties = new ArrayList<>(); } final String prList = getParameter(PROCEDURE, false); final List<String> procedures; if (prList != null) { procedures = StringUtilities.toStringList(prList); } else { procedures = new ArrayList<>(); } final String foList = getParameter(FEATURE_OF_INTEREST, false); final List<String> foids; if (foList != null) { foids = StringUtilities.toStringList(foList); } else { foids = new ArrayList<>(); } final String responseFormat = getParameter(RESPONSE_FORMAT, false); final String bboxStr = getParameter("spatialFilter", false); final Filter spatialFilter; if (bboxStr != null) { spatialFilter = parseBBoxFilter(bboxStr); } else { spatialFilter = null; } final String tempStr = getParameter("temporalFilter", false); final List<Filter> temporalFilters = new ArrayList<>(); if (tempStr != null) { temporalFilters.add(parseTemporalFilter(tempStr)); } return buildGetObservation(currentVersion, service, offering, observedProperties, procedures, foids, responseFormat, temporalFilters, spatialFilter, null, null, null, null); } else { throw new CstlServiceException("The operation GetObservation is only requestable in XML via POST method for 1.0.0 version", OPERATION_NOT_SUPPORTED, "GetObservation"); } } private BBOX parseBBoxFilter(final String bboxStr) { final String[] part = bboxStr.split(","); final String valueReference = part[0]; final double[] coord = new double[4]; int j = 0; for (int i=1; i < 5; i++) { coord[j] = Double.parseDouble(part[i]); j++; } final String srsName; if (part.length > 5) { srsName = part[5]; } else { srsName = "urn:ogc:def:crs:EPSG::4326"; } return buildBBOX("2.0.0", valueReference, coord[0], coord[1], coord[2], coord[3], srsName); } private Filter parseTemporalFilter(final String tempStr) { final String[] part = tempStr.split(","); final String valueReference = part[0]; final int slash = part[1].indexOf('/'); if (slash != -1) { final String dateBegin = part[1].substring(0, slash); final String dateEnd = part[1].substring(slash + 1); final Period period = buildTimePeriod("2.0.0", null, dateBegin, dateEnd); return buildTimeDuring("2.0.0", valueReference, period); } else { final Instant instant = buildTimeInstant("2.0.0", null, part[1]); return buildTimeEquals("2.0.0", valueReference, instant); } } }