/**
* Copyright (C) 2012 52°North Initiative for Geospatial Open Source Software GmbH
*
* 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.n52.sos.handler;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.n52.om.observation.MultiValueObservation;
import org.n52.ows.ExceptionReport;
import org.n52.ows.InvalidParameterValueException;
import org.n52.ows.NoApplicableCodeException;
import org.n52.sos.Constants;
import org.n52.sos.db.AccessGDB;
import org.n52.sos.encoder.AQDObservationEncoder;
import org.n52.sos.encoder.OGCObservationSWECommonEncoder;
import com.esri.arcgis.server.json.JSONObject;
/**
* @author <a href="mailto:broering@52north.org">Arne Broering</a>
*/
public class GetObservationOperationHandler extends OGCOperationRequestHandler {
private static final String GET_OBSERVATION_OPERATION_NAME = "GetObservation";
public static final String OM_PHENOMENON_TIME_LATEST = "om:phenomenonTime,latest";
public static final String OM_PHENOMENON_TIME_FIRST = "om:phenomenonTime,first";
private static final String VERSION_KEY = "version";
private static final String OFFERING_KEY = "offering";
private static final String FOI_KEY = "featureOfInterest";
private static final String OBSERVED_PROPERTY_KEY = "observedProperty";
private static final String PROCEDURE_KEY = "procedure";
private static final String SPATIAL_FILTER_KEY = "spatialFilter";
private static final String TEMPORAL_FILTER_KEY = "temporalFilter";
private static final String RESPONSE_FORMAT_KEY = "responseFormat";
private static final String AGGREGATION_TYPE = "aggregationType";
private static List<String> supportedValueReferences = Arrays.asList(new String[] {
"om:phenomenonTime"
});
public GetObservationOperationHandler() {
super();
}
/**
*
* @param inputObject
* @return
* @throws Exception
*/
public byte[] invokeOGCOperation(AccessGDB geoDB, JSONObject inputObject,
String[] responseProperties) throws ExceptionReport
{
super.invokeOGCOperation(geoDB, inputObject, responseProperties);
// check 'version' parameter:
checkMandatoryParameter(inputObject, VERSION_KEY, VERSION);
String[] offerings = null;
if (inputObject.has(OFFERING_KEY)) {
offerings = inputObject.getString(OFFERING_KEY).split(",");
}
String[] featuresOfInterest = null;
if (inputObject.has(FOI_KEY)) {
featuresOfInterest = inputObject.getString(FOI_KEY).split(",");
}
String[] observedProperties = null;
if (inputObject.has(OBSERVED_PROPERTY_KEY)) {
observedProperties = inputObject.getString(OBSERVED_PROPERTY_KEY).split(",");
}
String[] procedures = null;
if (inputObject.has(PROCEDURE_KEY)) {
procedures = inputObject.getString(PROCEDURE_KEY).split(",");
}
String spatialFilter = null;
if (inputObject.has(SPATIAL_FILTER_KEY)) {
String spatialFilterOGC = inputObject.getString(SPATIAL_FILTER_KEY);
spatialFilter = convertSpatialFilterFromOGCtoArcGisREST(spatialFilterOGC);
}
String temporalFilter = createTemporalFilter(inputObject);
String responseFormat = null;
if (inputObject.has(RESPONSE_FORMAT_KEY)) {
responseFormat = inputObject.getString(RESPONSE_FORMAT_KEY);
}
String[] aggregationTypes = null;
if (inputObject.has(AGGREGATION_TYPE)) {
aggregationTypes = inputObject.getString(AGGREGATION_TYPE).split(",");
}
String result;
Map<String, MultiValueObservation> observationCollection;
try {
observationCollection = geoDB.getObservationAccess().getObservations(offerings, featuresOfInterest, observedProperties, procedures, spatialFilter, temporalFilter, aggregationTypes, null);
if (responseFormat != null && responseFormat.equalsIgnoreCase(Constants.RESPONSE_FORMAT_RDF)) {
// constructInvokedURL(offerings, featuresOfInterest, observedProperties, procedures, spatialFilter, temporalFilter, responseFormat);
throw new UnsupportedOperationException("RDF not yet supported");
// result = new RDFEncoder(sosUrlExtension).getObservationCollectionTriples(observationCollection, invokedURL);
}
else if (responseFormat != null && responseFormat.equalsIgnoreCase(Constants.RESPONSE_FORMAT_AQ)) {
result = new AQDObservationEncoder().encodeObservations(observationCollection);
}
else if (responseFormat == null || responseFormat.equalsIgnoreCase(Constants.RESPONSE_FORMAT_OM)) {
result = new OGCObservationSWECommonEncoder().encodeObservations(observationCollection);
}
else {
throw new InvalidParameterValueException("Specified responseFormat '" + responseFormat + "' is unsupported. Please use either '"+Constants.RESPONSE_FORMAT_OM+"', '"+Constants.RESPONSE_FORMAT_AQ+"', or '"+Constants.RESPONSE_FORMAT_RDF+"'.");
}
return result.getBytes("utf-8");
} catch (IOException e) {
throw new NoApplicableCodeException(e);
}
}
private String createTemporalFilter(JSONObject inputObject)
throws InvalidParameterValueException {
String temporalFilter = null;
if (inputObject.has(TEMPORAL_FILTER_KEY)) {
String temporalFilterOGC = inputObject.getString(TEMPORAL_FILTER_KEY);
if (temporalFilterOGC.equals(OM_PHENOMENON_TIME_FIRST) ||
temporalFilterOGC.equals(OM_PHENOMENON_TIME_LATEST)) {
return temporalFilterOGC;
}
String[] params = temporalFilterOGC.split(",");
if (params.length != 2) {
throw new InvalidParameterValueException("The temporalFilter must consist of two comma separated values: valueReference,iso8601Time OR valueReference,<latest or first>");
}
/*
* TODO: once we decide to support other valueReferences we have to
* come up with a better mechanism (see also AccessGdbForObservationsImpl.createTemporalClauseSDE(String))
*/
if (!supportedValueReferences.contains(params[0].trim())) {
throw new InvalidParameterValueException("The value reference "+params[0].trim()+" is currently not supported for temporalFilter");
}
temporalFilter = convertTemporalFilterFromOGCtoArcGisREST(params[1].trim());
}
return temporalFilter;
}
protected String constructInvokedURL(String[] offerings,
String[] featuresOfInterest, String[] observedProperties,
String[] procedures, String spatialFilter, String temporalFilter, String responseFormat) {
StringBuilder invokedURL = new StringBuilder();
invokedURL.append(this.sosUrlExtension);
invokedURL.append("/GetObservation");
invokedURL.append("?service=").append(SERVICE);
invokedURL.append("&request=").append(getOperationName());
invokedURL.append("&version=").append(VERSION);
if (offerings != null) {
invokedURL.append("&offering=").append(createCommaSeperatedList(offerings));
}
if (featuresOfInterest != null) {
invokedURL.append("&featureOfInterest=").append(createCommaSeperatedList(featuresOfInterest));
}
if (observedProperties != null) {
invokedURL.append("&observedProperty=").append(createCommaSeperatedList(observedProperties));
}
if (procedures != null) {
invokedURL.append("&procedure=").append(createCommaSeperatedList(procedures));
}
if (spatialFilter != null) {
invokedURL.append("&spatialFilter=").append(spatialFilter);
}
if (temporalFilter != null) {
invokedURL.append("&temporalFilter=").append(temporalFilter);
}
if (responseFormat != null) {
invokedURL.append("&responseFormat=").append(responseFormat);
}
return invokedURL.toString();
}
private String createCommaSeperatedList(String[] offerings) {
StringBuilder sb = new StringBuilder();
sb.append(offerings[0]);
if (offerings.length == 1) return sb.toString();
for (int i = 1; i < offerings.length-1; i++) {
sb.append(offerings[i]);
sb.append(",");
}
sb.append(offerings[offerings.length-1]);
return sb.toString();
}
public static void main(String[] args)
{
String[] offerings = new String[]{"o1", "o2"};
String [] offeringsNew = new String[offerings.length + 1];
System.arraycopy(offerings, 0, offeringsNew, 0, offerings.length);
offeringsNew[offeringsNew.length - 1] = null;
for (int offeringIndex = 0; offeringIndex < offeringsNew.length; offeringIndex++) {
System.out.println(offeringsNew[offeringIndex]);
}
}
@Override
protected String getOperationName() {
return GET_OBSERVATION_OPERATION_NAME;
}
@Override
public int getExecutionPriority() {
return 0;
}
}