/** * 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; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.ServiceLoader; import org.joda.time.LocalTime; import org.n52.om.observation.MultiValueObservation; import org.n52.om.sampling.Feature; import org.n52.ows.ExceptionReport; import org.n52.ows.InvalidParameterValueException; import org.n52.ows.InvalidRequestException; import org.n52.ows.NoApplicableCodeException; import org.n52.ows.ResponseExceedsSizeLimitException; import org.n52.oxf.valueDomains.time.ITimePosition; import org.n52.oxf.valueDomains.time.TimeFactory; import org.n52.sos.cache.CacheException; import org.n52.sos.cache.CacheNotYetAvailableException; import org.n52.sos.cache.AbstractCacheScheduler; import org.n52.sos.cache.ObservationOfferingCache; import org.n52.sos.dataTypes.ObservationOffering; import org.n52.sos.dataTypes.Procedure; import org.n52.sos.dataTypes.ServiceDescription; import org.n52.sos.db.AccessGDB; import org.n52.sos.db.impl.AccessGDBImpl; import org.n52.sos.encoder.JSONEncoder; import org.n52.sos.encoder.JSONObservationEncoder; import org.n52.sos.handler.OGCOperationRequestHandler; import org.n52.sos.handler.OperationRequestHandler; import org.n52.util.ExceptionSupporter; import org.n52.util.VersionInfo; import org.n52.util.logging.Logger; import com.esri.arcgis.carto.IMapServer3; import com.esri.arcgis.carto.IMapServerDataAccess; import com.esri.arcgis.interop.AutomationException; import com.esri.arcgis.interop.extn.ArcGISExtension; import com.esri.arcgis.interop.extn.ServerObjectExtProperties; import com.esri.arcgis.server.IServerObjectExtension; import com.esri.arcgis.server.IServerObjectHelper; import com.esri.arcgis.server.SOAPRequestHandler; import com.esri.arcgis.server.json.JSONArray; import com.esri.arcgis.server.json.JSONObject; import com.esri.arcgis.system.IObjectConstruct; import com.esri.arcgis.system.IPropertySet; import com.esri.arcgis.system.IRESTRequestHandler; import com.esri.arcgis.system.ServerUtilities; /** * The main class of this ArcGIS Server Object Extension (SOE). * * @author <a href="mailto:broering@52north.org">Arne Broering</a> */ @ArcGISExtension @ServerObjectExtProperties( displayName = "An_SOS_extension_for_ArcGIS_Server", description = "An_SOS_extension_for_ArcGIS_Server" ) public class SosSoe extends SOAPRequestHandler implements IServerObjectExtension, IObjectConstruct, ISosTransactionalSoap, IRESTRequestHandler { private static final long serialVersionUID = 1L; private IMapServerDataAccess mapServerDataAccess; public Logger LOGGER = Logger.getLogger(SosSoe.class.getName()); protected AccessGDB geoDB; //private ObservationGDBInserter geoDBInserter; private String urlSosExtension; private String sosTitle; private String sosDescription; private String sosKeywords; private String sosProviderName; private String sosProviderSite; private String sosContactPersonName; private String sosContactPersonPosition; private String sosContactPersonPhone; private String sosContactPersonFax; private String sosContactPersonAddress; private String sosContactPersonCity; private String sosContactPersonAdminArea; private String sosContactPersonPostalCode; private String sosContactPersonCountry; private String sosContactPersonEmail; private int maximumRecordCount; private List<OperationRequestHandler> operationHandlers; private AbstractCacheScheduler cacheScheduler; private boolean updateCacheOnStartup; private LocalTime cacheUpdateTime; /** * constructs a new server object extension * * @throws Exception */ public SosSoe() throws Exception { super(); } /************************************************************************************* * IServerObjectExtension methods: *************************************************************************************/ /** * init() is called once, when the instance of the SOE is created. */ public void init(IServerObjectHelper soh) throws IOException, AutomationException { Logger.init(ServerUtilities.getServerLogger()); LOGGER.info("Start initializing SOE"); LOGGER.info(new VersionInfo().toString()); this.mapServerDataAccess = (IMapServerDataAccess) soh.getServerObject(); LOGGER.info(this.getClass().getName() + " initialized."); } /** * shutdown() is called once when the Server Object's context is being shut * down and is about to go away. */ public void shutdown() throws IOException, AutomationException { /* * The SOE should release its reference on the Server Object Helper. */ LOGGER.info("Shutting down " + this.getClass().getName() + " SOE."); this.mapServerDataAccess = null; this.cacheScheduler.shutdown(); // TODO make sure all references are being cut. } /************************************************************************************* * IConstructObject methods: *************************************************************************************/ /** * construct() is called only once, when the SOE is created, after IServerObjectExtension.init() * is called. This method hands back the configuration properties for the SOE as a property set. * You should include any expensive initialization logic for your SOE within your implementation * of construct(). */ public void construct(IPropertySet propertySet) throws IOException { try { LOGGER.info("Reading properties..."); String specifiedUrlSosExtension = (String) propertySet.getProperty("urlSosExtension"); // cut off '/' if necessary: if(specifiedUrlSosExtension.charAt(specifiedUrlSosExtension.length() - 1) == '/') { this.urlSosExtension = specifiedUrlSosExtension.substring(0, specifiedUrlSosExtension.length() - 1); } else { this.urlSosExtension = specifiedUrlSosExtension; } this.sosTitle = (String) propertySet.getProperty("title"); this.sosDescription = (String) propertySet.getProperty("description"); this.sosKeywords = (String) propertySet.getProperty("keywords"); this.sosProviderName = (String) propertySet.getProperty("providerName"); this.sosProviderSite = (String) propertySet.getProperty("providerSite"); this.sosContactPersonName = (String) propertySet.getProperty("contactPersonName"); this.sosContactPersonPosition = (String) propertySet.getProperty("contactPersonPosition"); this.sosContactPersonPhone = (String) propertySet.getProperty("contactPersonPhone"); this.sosContactPersonFax = (String) propertySet.getProperty("contactPersonFax"); this.sosContactPersonAddress = (String) propertySet.getProperty("contactPersonAddress"); this.sosContactPersonCity = (String) propertySet.getProperty("contactPersonCity"); this.sosContactPersonAdminArea = (String) propertySet.getProperty("contactPersonAdminArea"); this.sosContactPersonPostalCode = (String) propertySet.getProperty("contactPersonPostalCode"); this.sosContactPersonCountry = (String) propertySet.getProperty("contactPersonCountry"); this.sosContactPersonEmail = (String) propertySet.getProperty("contactPersonEmail"); Object updateCache = propertySet.getProperty("updateCacheOnStartup"); if (updateCache != null) { this.updateCacheOnStartup = Boolean.parseBoolean(updateCache.toString()); } LOGGER.info("Update cache on startup? "+ this.updateCacheOnStartup +" object: "+ updateCache); Object cacheUpdateTime = propertySet.getProperty("cacheUpdateTime"); if (cacheUpdateTime != null) { try { this.cacheUpdateTime = new LocalTime(cacheUpdateTime.toString()); } catch (Exception e) { LOGGER.warn("Using fallback cache update Time - Could not parse cacheUpdateTime: "+cacheUpdateTime.toString(), e); this.cacheUpdateTime = new LocalTime("04:00:00"); } } LOGGER.info("Cache update time: "+ this.cacheUpdateTime +" object: "+ cacheUpdateTime); } catch (Exception e) { LOGGER.severe("There was a problem while reading properties: \n" + e.getLocalizedMessage() + "\n" + ExceptionSupporter.createStringFromStackTrace(e)); throw new IOException(e); } resolveServiceProperties(); initializeOperationHandlers(); try { // create database access this.geoDB = new AccessGDBImpl(this); } catch (Exception e) { LOGGER.severe("There was a problem while creating DB access: \n" + e.getLocalizedMessage() + "\n" + ExceptionSupporter.createStringFromStackTrace(e)); throw new IOException(e); } /* * initiate the cache */ cacheScheduler = AbstractCacheScheduler.Instance.init(geoDB, this.updateCacheOnStartup, this.cacheUpdateTime); LOGGER.info("Construction of SOE finished."); } private void resolveServiceProperties() { if (this.mapServerDataAccess instanceof IMapServer3) { try { IPropertySet propertySet = ((IMapServer3) this.mapServerDataAccess).getServiceConfigurationInfo(); Object value = propertySet.getProperty("MaximumRecordCount"); if (value != null) { this.maximumRecordCount = (int) value; } } catch (AutomationException e) { LOGGER.warn(e.getMessage()); } catch (IOException e) { LOGGER.warn(e.getMessage()); } } } private void initializeOperationHandlers() { ServiceLoader<OperationRequestHandler> loader = ServiceLoader.load(OperationRequestHandler.class); this.operationHandlers = new ArrayList<OperationRequestHandler>(); for (OperationRequestHandler h : loader) { h.initialize(this.urlSosExtension); this.operationHandlers.add(h); LOGGER.info("init op handler " + h.getExecutionPriority() + " added"); } Collections.sort(this.operationHandlers); LOGGER.info("Registered Operation Handlers: " + this.operationHandlers.toString()); } /************************************************************************************* * SOAP methods: *************************************************************************************/ /** * @throws UnsupportedEncodingException * */ @Override public String insertObservation(int offeringID, String phenomenonTime, int featureID, int observedPropertyID, int procedureID, float result) { try { String request = ""; request += "offering = " + offeringID + "\n"; request += "phenomenonTime = " + phenomenonTime + "\n"; request += "feature = " + featureID + "\n"; request += "observedProperty = " + observedPropertyID + "\n"; request += "procedure = " + procedureID + "\n"; request += "result = " + result + "\n"; LOGGER.info("Incoming SOAP request parameters: " + request); ITimePosition t = (ITimePosition)TimeFactory.createTime(phenomenonTime); Date phenomenonTimeAsDate = t.getCalendar().getTime(); int observationID = this.geoDB.getObservationInsert().insertObservation(offeringID, phenomenonTimeAsDate, featureID, observedPropertyID, procedureID, result); return "" + observationID; } catch (Exception e) { LOGGER.severe("There was a problem while answering the SOAP request: \n" + e.getLocalizedMessage() + "\n" + ExceptionSupporter.createStringFromStackTrace(e)); return "There was a problem while answering the SOAP request: \n" + e.getLocalizedMessage() + "\n" + ExceptionSupporter.createStringFromStackTrace(e); } } /************************************************************************************* * IRESTRequestHandler methods: *************************************************************************************/ /** * This method returns the resource hierarchy of a REST based SOE in JSON * format. */ @Override public String getSchema() throws IOException, AutomationException { LOGGER.debug("getSchema() is called..."); return createSchema(); } /** * Testable support method for getSchema(). */ protected static String createSchema() throws IOException, AutomationException { JSONObject arcGisSos = ServerUtilities.createResource("ArcGIS_SOS_Extension", "An_SOS_extension_for_ArcGIS_Server", false, false); JSONArray ogcOperationArray = new JSONArray(); // create a schema object for the 'observations' resource: JSONObject observationsObject = ServerUtilities.createResource("observations", "description of observations resource", false, false); JSONArray observationsQueryOp = new JSONArray(); observationsQueryOp.put(ServerUtilities.createOperation("query", "offering, observedProperty, procedure, featureOfInterest, spatialFilter, temporalFilter, aggregationType, where", "json", false)); observationsObject.put("operations", observationsQueryOp); // observationsQueryOp.put(ServerUtilities.createOperation("diagram", "offering, observedProperty, procedure, featureOfInterest, spatialFilter, temporalFilter, where", "jpeg", false)); // observationsObject.put("operations", observationsQueryOp); // create a schema object for the 'procedure' resource: JSONObject procedureObject = ServerUtilities.createResource("procedures", "description of procedure resource", true, true); // JSONArray proceduresQueryOp = new JSONArray(); // proceduresQueryOp.put(ServerUtilities.createOperation("query", "procedure", "json", false)); // procedureObject.put("operations", proceduresQueryOp); // create a schema object for the 'features' resource: /* JSONObject featuresObject = ServerUtilities.createResource("features", "description of features resource", false, false); JSONArray featuresQueryOp = new JSONArray(); featuresQueryOp.put(ServerUtilities.createOperation("query", "feature, observedProperty, procedure, spatialFilter", "json", false)); featuresObject.put("operations", featuresQueryOp); */ // create a schema object for the GetCapabilities operation: ogcOperationArray.put(ServerUtilities.createOperation("GetCapabilities", "service, request", "json, xml", false)); // create a schema object for the GetObservation operation: ogcOperationArray.put(ServerUtilities.createOperation("GetObservation", "service, version, request, offering, observedProperty, procedure, featureOfInterest, namespaces, spatialFilter, temporalFilter, aggregationType, responseFormat", "json, xml", false)); // create a schema object for the DescribeSensor operation: ogcOperationArray.put(ServerUtilities.createOperation("DescribeSensor", "service, version, request, procedure, procedureDescriptionFormat", "json, xml", false)); // create a schema object for the GetObservationByID operation: ogcOperationArray.put(ServerUtilities.createOperation("GetObservationByID", "service, version, request, observation, responseFormat", "json, xml", false)); // create a schema object for the GetFeatureOfInterest operation: ogcOperationArray.put(ServerUtilities.createOperation("GetFeatureOfInterest", "service, version, request, featureOfInterest, observedProperty, procedure, namespaces, spatialFilter", "json, xml", false)); ogcOperationArray.put(ServerUtilities.createOperation("GetCacheMetadata", "service, version, request", "json", false)); // include all resource objects into 'resources' array: JSONArray resourceArray = new JSONArray(); resourceArray.put(observationsObject); resourceArray.put(procedureObject); /* resourceArray.put(featuresObject); */ arcGisSos.put("resources", resourceArray); arcGisSos.put("operations", ogcOperationArray); return arcGisSos.toString(); } /** * This method handles REST requests by determining whether an operation or * resource has been invoked and then forwards the request to appropriate * methods. * * @param capabilities * The capabilities supported by the SOE. An admin can choose * which capabilities are enabled on a particular SOE (in ArcGIS * Manager or ArcCatalog), based on certain criteria such as * security roles. This list of allowed capabilities is then sent * to this method, at runtime, as a comma separated list. * @param resourceName * Name of the resource being addressed relative to the root SOE * resource. If empty, its assumed that root resource is being * addressed. E.g.: "procedures/mysensor123". For resource * requests, the operationName parameter of this method will be * an empty string (""). * @param operationName * Name of the operation being invoked. If empty, description of * resource is returned. * @param operationInput * Input parameters to the operation specified by operationName * parameter, encoded as a JSON formatted string. The REST * handler coerces the input parameters of an operation into a * JSON string. The request parameter names become the JSON * property names. The values are attempted to be coerced to * valid JSON types - numbers, booleans, JSON objects, JSON * arrays. If they cannot be coerced to any of the types * mentioned above, they'll be treated as strings. * @param outputFormat * OutputFormat of operation. The value of the format parameter f * of the REST API. */ @Override public byte[] handleRESTRequest(String capabilities, String resourceName, String operationName, String operationInput, String outputFormat, String requestProperties, String[] responseProperties) throws IOException, AutomationException { if (this.cacheScheduler.isCurrentyLocked()) { throw new IOException("A database maintenance is currently in progress. Please come back in a few minutes"); } LOGGER.debug("Starting to handle REST request..."); // LOGGER.info("capabilities: " + capabilities); // LOGGER.info("resourceName: " + resourceName); // LOGGER.info("operationName: " + operationName); // LOGGER.info("operationInput: " + operationInput); // LOGGER.info("outputFormat: " + outputFormat); // LOGGER.info("requestProperties: " + requestProperties); try { // if no operationName is specified send description of specified // resource if (operationName.length() == 0) { return getResource(resourceName, operationInput); } else { if (geoDB == null) { throw new NullPointerException("Database connection null."); } // extract operation input parameters to Map: JSONObject inputObject = new JSONObject(operationInput); // handle: observations/query if (resourceName.equals("observations") && operationName.equalsIgnoreCase("query")) { return invokeObservationQueryOperation(inputObject, outputFormat, responseProperties); } /* // handle: observations/diagram else if (resourceName.equals("observations") && operationName.equalsIgnoreCase("diagram")) { return invokeObservationDiagramOperation(inputObject, outputFormat, responseProperties); } */ // handle: features/query else if (resourceName.equals("features") && operationName.equalsIgnoreCase("query")) { return invokeFeatureQueryOperation(inputObject); } // handle: procedures/query else if (resourceName.equals("procedures") && operationName.equalsIgnoreCase("query")) { return invokeProcedureQueryOperation(inputObject); } else { OperationRequestHandler handler = resolveHandler(operationName); return handler.invokeOGCOperation(geoDB, inputObject, responseProperties); } } } catch (ExceptionReport e) { LOGGER.info("OWS ExceptionReport thrown: \n" + e.getLocalizedMessage() + "\n" + ExceptionSupporter.createStringFromStackTrace(e)); return prepareExceptionResponse(e, responseProperties); } catch (IOException | RuntimeException e) { LOGGER.severe("Error while handle REST request: \n" + e.getLocalizedMessage() + "\n" + ExceptionSupporter.createStringFromStackTrace(e)); return prepareExceptionResponse(new NoApplicableCodeException(e), responseProperties); } } private byte[] prepareExceptionResponse(ExceptionReport e, String[] responseProperties) { responseProperties[0] = OGCOperationRequestHandler.DEFAULT_RESPONSE_PROPERTIES; try { return e.toString().getBytes("utf-8"); } catch (UnsupportedEncodingException e1) { LOGGER.severe(e1.getMessage(), e1); throw new RuntimeException(e1); } } private OperationRequestHandler resolveHandler(String operationName) throws InvalidRequestException { for (OperationRequestHandler h : this.operationHandlers) { try { if (h.canHandle(operationName)) { return h; } } catch (RuntimeException e) { LOGGER.warn("Error while resolving handler", e); } } throw new InvalidRequestException("Operation '" + operationName + "' not supported on this resource."); } /************************************************************************************* * Private, supporting & helper methods: * @throws IOException * @throws InvalidRequestException * @throws ResponseExceedsSizeLimitException *************************************************************************************/ /* protected byte[] invokeObservationDiagramOperation(JSONObject inputObject, String outputFormat, String[] responseProperties) throws Exception { LOGGER.info("Start observation/diagram operation."); String[] offerings = null; if (inputObject.has("offering")) { offerings = inputObject.getString("offering").split(","); } String[] featuresOfInterest = null; if (inputObject.has("featureOfInterest")) { featuresOfInterest = inputObject.getString("featureOfInterest").split(","); } String[] observedProperties = null; if (inputObject.has("observedProperty")) { observedProperties = inputObject.getString("observedProperty").split(","); } String[] procedures = null; if (inputObject.has("procedure")) { procedures = inputObject.getString("procedure").split(","); } String spatialFilter = null; if (inputObject.has("spatialFilter")) { spatialFilter = inputObject.getString("spatialFilter"); } String temporalFilter = null; if (inputObject.has("temporalFilter")) { temporalFilter = inputObject.getString("temporalFilter"); } String where = null; if (inputObject.has("where")) { where = inputObject.getString("where"); } GenericObservationCollection observations = this.geoDB.getObservations(offerings, featuresOfInterest, observedProperties, procedures, spatialFilter, temporalFilter, where); BufferedImage img = new TimeSeriesChartRenderer4xPhenomenons().createChartImage(observations); ByteArrayOutputStream out = new ByteArrayOutputStream(1024); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(img); param.setQuality(1, false); encoder.encode(img, param); responseProperties = new String[] { "{\"Content-Type\" : \"image/jpeg\"}" }; responseProperties = new String[]{"{\"Content-Disposition\" : inline; filename=\"sos-image.jpeg\"}"}; return out.toByteArray(); } */ protected byte[] invokeObservationQueryOperation(JSONObject inputObject, String outputFormat, String[] responseProperties) throws ResponseExceedsSizeLimitException, InvalidRequestException, IOException { LOGGER.info("Start observation query."); String[] offerings = null; if (inputObject.has("offering")) { offerings = inputObject.getString("offering").split(","); } String[] featuresOfInterest = null; if (inputObject.has("featureOfInterest")) { featuresOfInterest = inputObject.getString("featureOfInterest").split(","); } String[] observedProperties = null; if (inputObject.has("observedProperty")) { observedProperties = inputObject.getString("observedProperty").split(","); } String[] procedures = null; if (inputObject.has("procedure")) { procedures = inputObject.getString("procedure").split(","); } String spatialFilter = null; if (inputObject.has("spatialFilter")) { spatialFilter = inputObject.getString("spatialFilter"); } String temporalFilter = null; if (inputObject.has("temporalFilter")) { temporalFilter = inputObject.getString("temporalFilter"); } String[] aggregationTypes = null; if (inputObject.has("aggregationType")) { aggregationTypes = inputObject.getString("aggregationType").split(","); } String where = null; if (inputObject.has("where")) { where = inputObject.getString("where"); } Map<String, MultiValueObservation> observations = this.geoDB.getObservationAccess().getObservations(offerings, featuresOfInterest, observedProperties, procedures, spatialFilter, temporalFilter, aggregationTypes, where); JSONObject json = JSONObservationEncoder.encodeObservations(observations); return json.toString().getBytes("utf-8"); } protected byte[] invokeFeatureQueryOperation(JSONObject inputObject) throws ExceptionReport, IOException { LOGGER.info("Start feature query."); JSONObject json = null; String[] features = null; if (inputObject.has("feature")) { features = inputObject.getString("feature").split(","); } String[] observedProperties = null; if (inputObject.has("observedProperty")) { observedProperties = inputObject.getString("observedProperty").split(","); } String[] procedures = null; if (inputObject.has("procedure")) { procedures = inputObject.getString("procedure").split(","); } String spatialFilter = null; if (inputObject.has("spatialFilter")) { spatialFilter = inputObject.getString("spatialFilter"); } Collection<Feature> fois = this.geoDB.getFeatureAccess().getFeaturesOfInterest(features, observedProperties, procedures, spatialFilter); json = JSONEncoder.encodeSamplingFeatures(fois); return json.toString().getBytes("utf-8"); } protected byte[] invokeProcedureQueryOperation(JSONObject inputObject) throws IOException { LOGGER.info("Start procedures query."); JSONObject json = null; String[] procedures = null; if (inputObject.has("procedure")) { procedures = inputObject.getString("procedure").split(","); } Collection<Procedure> proceduresColl = this.geoDB.getProcedureAccess().getProceduresWithIdAndResource(procedures); if (json == null) { json = JSONEncoder.encodeProcedures(proceduresColl); } return json.toString().getBytes("utf-8"); } /** * Returns JSON representation of specified resource. * * @param resourceName * Name of the resource being addressed relative to the root SOE * resource. If empty, its assumed that root resource is being * addressed. E.g.: "procedures/mysensor123". * * @return JSON representation of specified resource as a byte[]. * @throws IOException */ public byte[] getResource(String resourceName, String operationInput) throws IOException, ExceptionReport { // TODO consider operationInput LOGGER.info("getResource() is called."); if (geoDB == null) { throw new NullPointerException("Database access object not instantiated."); } // this.serverLog.addMessage(1, 8000, "getResource() is called."); JSONObject json = null; // root resource is accessed: if (resourceName.equalsIgnoreCase("") || resourceName.length() == 0) { ServiceDescription serviceDesc = geoDB.getServiceDescription(); json = JSONEncoder.encodeServiceDescription(serviceDesc); } else if (resourceName.matches("observations")) { Collection<ObservationOffering> offerings; try { offerings = ObservationOfferingCache.instance(this.geoDB.getDatabaseName()).getEntityCollection(geoDB).values(); } catch (CacheException | CacheNotYetAvailableException e) { throw new NoApplicableCodeException(e); } json = JSONEncoder.encodeObservationOfferings(offerings); } // handle queries for procedures: else if (resourceName.matches("procedures")) { List<String> procedureIDArray = geoDB.getProcedureAccess().getProcedureIdList(); json = JSONEncoder.encodeProcedureIDs(procedureIDArray); } else if (resourceName.matches("procedures/.+")) { String procedureID = resourceName.split("/")[1]; // LOGGER.info("Procedure requested: '" + procedureID + "'"); Collection<Procedure> proceduresFromDB = geoDB.getProcedureAccess().getProceduresWithIdAndResource(new String[] { procedureID }); // LOGGER.info("Count of procedures returned from DB: " + proceduresFromDB.size()); if (proceduresFromDB.size() == 1) { Procedure p = proceduresFromDB.iterator().next(); json = JSONEncoder.encodeProcedure(p); } else if (proceduresFromDB.size() > 1) { json = JSONEncoder.encodeProcedures(proceduresFromDB); } else if (proceduresFromDB.size() == 0) { throw new InvalidParameterValueException("Procedure with name: '" + procedureID + "' not in DB."); } } // handle queries for features: else if (resourceName.matches("features")) { Collection<Feature> fois = geoDB.getFeatureAccess().getFeaturesOfInterest(null, null, null, null); json = JSONEncoder.encodeSamplingFeaturesIDs(fois); } /* else if (resourceName.matches("features/.+")) { String foiName = resourceName.split("/")[1]; LOGGER.info("Feature requested: '" + foiName + "'"); Collection<SpatialSamplingFeature> foisFromDB = geoDB.getFeaturesOfInterest(new String[] { foiName }, null, null, null); LOGGER.info("Count of features returned from DB: " + foisFromDB.size()); if (foisFromDB.size() == 1) { SpatialSamplingFeature foi = foisFromDB.iterator().next(); json = JSONEncoder.encodeSamplingFeature(foi); } else if (foisFromDB.size() > 1) { json = JSONEncoder.encodeSamplingFeatures(foisFromDB); } else if (foisFromDB.size() == 0) { throw new Exception("Feature with name: '" + foiName + "' not in DB."); } } */ return json.toString().getBytes("utf-8"); } // // ------------------------ getters ----------------------------- // public IMapServerDataAccess getMapServerDataAccess() { return this.mapServerDataAccess; } public String getUrlSosExtension() { return urlSosExtension; } public int getMaximumRecordCount() { return maximumRecordCount; } public String getSosTitle() { return sosTitle; } public String getSosDescription() { return sosDescription; } public String getSosKeywords() { return sosKeywords; } public String getSosProviderName() { return sosProviderName; } public String getSosProviderSite() { return sosProviderSite; } public String getSosContactPersonName() { return sosContactPersonName; } public String getSosContactPersonPosition() { return sosContactPersonPosition; } public String getSosContactPersonPhone() { return sosContactPersonPhone; } public String getSosContactPersonFax() { return sosContactPersonFax; } public String getSosContactPersonAddress() { return sosContactPersonAddress; } public String getSosContactPersonCity() { return sosContactPersonCity; } public String getSosContactPersonAdminArea() { return sosContactPersonAdminArea; } public String getSosContactPersonPostalCode() { return sosContactPersonPostalCode; } public String getSosContactPersonCountry() { return sosContactPersonCountry; } public String getSosContactPersonEmail() { return sosContactPersonEmail; } public boolean isUpdateCacheOnStartup() { return updateCacheOnStartup; } }