Exchangeable Encoding Plugin
Overview
(
AlexanderKmoch - 2012-08-20)
Within the
52°North's participation in the
Google Summer of Code program, an
exchangeable encoding mechanism has been developed and demonstrated.
The SOS standard response encoding is the OGC
Observations & Measurement XML representation for the SOS GetObservation request. But particular domains might be interested in either more domain-specific, e.g. application schemas, or more efficient data encoding. within this project, the 52°North SOS server has been modified to deliver additional encodings. Demo encodings are a simple CSV output and WaterML2.0. A SOS GetCapabilites response will list those additional encodings per SOS version. In a GetObservation request you can then enter another responseFormat parameter and result in a GetObservation response in the requested encoding.
The described mechanism changes parts of the SOS server, so that additional encodings could be implemented and delivered as a .jar file, which could easily be loaded through the SOS server itself. It would then read from that plugin, which encodings and for what SOS service versions are provided, add the encodings/response formats to the GetCapabilities document. When a GetObservation request is issued, it would choose the particular encoder based on the response format and service version tuple. Important details in short:
Installation and getting this customised SOS server version running is straightforward as the usual 52°North SOS server install
wiki page
Checkout the source here
https://svn.52north.org/svn/swe/main/SOS/Service/tags/ and/or have an online test to see how it looks like on the 52°North Google Summer of Code demo server
http://gsoc.dev.52north.org/
Demo requests:
Implemented Encodings
See
SosEncodings.
Technical Details
(
AlexanderKmoch - 2012-08-20)
For developers, who would either like to develop own encoding modules or integrate the exchangeable encoding mechanism in their (probably customised) SOS server version, please read here which parts of the code have been touched and how the plugin loading works. That mechanism will be incorporated in the next major SOS server version. For more information regarding setting up SOS server development have a look in the wiki
https://wiki.52north.org/bin/view/SensorWeb/SosEclipseJavaProject
The API uses the Java
!ServiceLoader facilities, to load classes via their interface. ServiceLoader come natively with JDK 6 and comprise a simple dependency injection framework. ServiceLoader classes based on flat file naming in the directory META-INF/services from the Java classpath. The mechanism of using META-INF/services has been around since JDK 1.3, under the name the Java Extension Mechanism. ServiceLoader makes it easier to use. In our case we use it to add additional observation encoders. These classes are put in to a map and are retrievable at runtime from the SosConfigurator and an be referenced through a "key object" based on the resonseFormat and the SOS service version. The responseFormat is also added to the Capabilities operations metadata and evaluated by the GetObservationListener, to call the right encoder.
To built a custom encoder, you would do the following:
- create a parallel maven module in your local copy of the SOS source code tree, keep the pom.xml simply as you need
- 52n-sos-coding-csv/src/main/java/org/n52/sos/encode/CSVEncoder.java
- create a simple textfile based on following scheme
- 52n-sos-coding-csv/src/main/resources/META-INF/services/org.n52.sos.encode.IObservationEncoder
- write the package plus class/name into that file, e.g. "org.n52.sos.encode.CSVEncoder"
- implement the interface methods
- latest source is in the SVN
Basic Code example
The simple CSVEncoder example is doing the following:
- implements the IObservationEncoder interface and methods
- needs to provide the EncodingKey(s)
- need to provide contentType
- need to check within class, how to separately do encoding
Development SOS internals
(52n-sos-core) org.n52.sos.GetObservationListerner.java
- in the main method "public synchronized ISosResponse receiveRequest(AbstractSosRequest request)" the encoder map is fetched from the SosConfigurator and will be used for "!checkResponseFormat" and to get an encoder for the requested responseFormat within the sections for SOS version 1 and 2, after O&M and ZIP responseFormats are handled
- the encoder output is put into a "ByteArrayOutputStream"
- a "!SosResponse" is created with the encoder output and the contentType and is now ready to be send back to the user
(52n-sos-core) org.n52.sos.resp.SosResponse.java
- the "!SosResponse" implements the "!ISosResponse" interface to be instantiated in the "!GetObservationListener", filled with the "!ByteArrayOutputStream" and to indicate the contentType for the SOS servlet
- !contentType should be used for the constructor, if input is not XML (to avoid SOAp envelope etc for e.g. CSV or binary encodings)
(52n-sos-core) org.n52.sos.encode.IObservationEncoder.java
This is the interfcae, which needs to be implemented by custom encoders, i.e. especially offers the method to encode observation collection for a GetObservation response
- public ByteArrayOutputStream createObservationCollection(SosObservationCollection sosObsCol) throws OwsExceptionReport; // the work horse
- public String createCompositePhenomenon(String compPhenId, Collection<String> phenComponents) throws OwsExceptionReport;
- public String getContentType(); // used later on to decide the content/mime type of the response
- public EncodingKey[] getEncodingKeys(); // a key class to indicate, which responseFormats for which SOS service version are provided
(52n-sos-core) org.n52.sos.utilities.GenericObservationEncodingType.java
This is the key class, used to map responseFormats+SOS version to the encoder in the ObservationEncoderMap (from SosConfigurator)
- private String responseFormat;
- private String version;
- setters/getters
- overridden hashcode and equals methods
(52n-sos-core) org.n52.sos.SosConfigurator.java
Most changes have been done in the SosConfigurator, the Java ServiceLoader additional encoding plugins are loaded, instantiated and sorted into a Map, which is used in most of the other here described parts of the SOS server.
- public Map<!GenericObservationEncodingType, IGenericObservationEncoder> getGenericObservationEncoderMap();
- private void setGenericObservationEncoderMap();
- private void initializeServiceLoaderGenericObservation();
- public void updateGenericObservationEncoderMap();
- private void initialize(); // calls initializeServiceLoaderGenericObservation();
(52n-sos-dao-postgres) org.n52.sos.ds.pgsql.PGSQLGetCapabilitiesDAO.java
To get the additional responseFromats visible in the GetCapabilities response document, they are fetched from the SosConfigurator here and added:
- private void setResponseFormats(SosCapabilities sosCapabilities, !OWSOperationsMetadata opsMeta)
- private List<!SosOfferingsForContents> getContents(SosCapabilities sosCapabilities)
- private List<!SosOfferingsForContents> getContentsForSosV2(!SosCapabilities sosCapabilities)