Extending an Encoder

Feedback


Here is an example of extending the spatial analysis output format of the geometry object (like geometryBufferResult). A pseudo KML format is added. That is to say, a simple KML region is generated according to the result region.

Implementation of new encoder pseudo KML

Firstly, determine the media type of the KML representation is "application/mykml". And in the iServer6R, if ".kml" is appended to the end of the URI when performing a GET request, the iServer6R server will return the HTTP response in "application/mykml" (To know how to explicitly configure the media type, please refer to Extending Media Types);

Secondly, use @Provider to register the customized MessageBodyProvider, namely FakeKMLEncoder, based on javax.ws.rs.ext.MessageBodyWriter and use @Produces to specify the media type as "application/mykml";

Thirdly, customize a KML file to represent a region object.

Fourthly, judges whether the response can be parsed into "application/mykml". If yes, a kml file will be returned.

The code for the above process are as follows, and the code file can be found in %SuperMap iServer Java_HOME%\samples\code\ExtendExist_JSR\FakeKMLEncoder.java.

package com.supermap.sample.extend;

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.Writer;

import java.lang.annotation.Annotation;

import java.lang.reflect.Type;

import javax.ws.rs.Produces;

import javax.ws.rs.WebApplicationException;

import javax.ws.rs.core.MediaType;

import javax.ws.rs.core.MultivaluedMap;

import javax.ws.rs.ext.MessageBodyWriter;

import javax.ws.rs.ext.Provider;

import com.supermap.services.components.commontypes.Geometry;

import com.supermap.services.components.commontypes.GeometrySpatialAnalystResult;

import com.supermap.services.components.commontypes.Point2D;

@Provider

@Produces("application/mykml")

public class FakeKMLEncoder implements MessageBodyWriter {

        // Determine the length of the object to be written in after serialization, with -1 indicateing unknown.

        public long getSize(Object object, Class type, Type genericType,

                        Annotation[] annotations, MediaType mediaType) {

                return -1;

        }

        /**

         * <p>

         * Judges whether the application/kml media type is supported

         * </p>

         */

        public boolean isWriteable(Class type, Type genericType,

                        Annotation[] annotations, MediaType mediaType) {

                if (mediaType.equals(new MediaType("application", "mykml"))) {

                        return true;

                }

                return false;

        }

        public void writeTo(Object resourceObj, Class type, Type genericType,

                        Annotation[] annotations, MediaType mediaType,

                        MultivaluedMap httpHeaders, OutputStream entityStream)

                        throws IOException, WebApplicationException {

                String result;

                // KML name (<name/> tag)

                String resultName = "result.kml";

                if (resourceObj instanceof Geometry) {

                        Geometry geometry = (Geometry) resourceObj;

                        result = this.createKMLRegion(resultName, geometry);

                } else if (resourceObj instanceof GeometrySpatialAnalystResult) {

                        Geometry geometry = ((GeometrySpatialAnalystResult) resourceObj).resultGeometry;

                        result = this.createKMLRegion(resultName, geometry);

                } else {

                        result = " The response is not a valid Geometry object";

                }

                // Write the KML file into entityStream, as the message body of the KML representation.

                Writer writer = new BufferedWriter(new OutputStreamWriter(entityStream,

                                "utf-8"));

                writer.write(result.toString(), 0, result.length());

                writer.close();

        }

        // Convert a Geometry into into a KML represented region.

        private String createKMLRegion(String filename, Geometry geometry) {

                Point2D[] points = geometry.points;

                // Convert into point set (<coordinates/> tag content)

                String coordinates = "";

                for (Point2D point : points) {

                        coordinates += point.x + "," + point.y + "," + "0 \n";

                }

                // The customized KML file, a region object

                StringBuffer sb = new StringBuffer();

                sb.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");

                sb.append("<Placemark>\n");

                sb.append("<name>" + filename + "</name>\n");

                sb.append("<Polygon>\n<outerBoundaryIs>\n<LinearRing>\n<coordinates>\n");

                sb.append(coordinates);

                sb.append("</coordinates>\n</LinearRing>\n</outerBoundaryIs>\n</Polygon>\n");

                sb.append("</Placemark>\n");

                sb.append("</kml>");

                return sb.toString();

        }

}

Pseudo KML representation configuration

Please refer to Configuration Files to learn the configuration method of the module configuration file. Add the content below to [Jar package] \META-INF\extensions\services\restSpatialAnalystRest:

encoders=com.supermap.sample.extend.FakeKMLEncoder

resourceFiles=MyBufferAnalystRest.xml

Complete the configuration by exporting the project ExtendExist_JSR where the code is located into JAR package (see extendexist_jsr.jar) and placing the package in %SuperMap iServer Java_HOME%\webapps\iserver\WEB-INF\lib.

The sample code can be seen in %SuperMap iServer Java_HOME%\samples\code\ExtendExist_JSR. It can be used in Eclipse by directly importing in. Note that when exporting the Jar package in Eclipse, check "Add directory entries", as shown below:

Use of the pseudo KML representation

Here is an example of introducing the KML representation usage through Geometry buffer analysis. Start the SuperMap iServer service, access the resource: http://supermapiserver:8090/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst/geometry/buffer, and change the buffer distance to 1, with all the other setting unchanged. Implement a POST request and get the response: http://supermapiserver:8090/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst/geometry/buffer/1.mykml.

Save the 1.mykml file to local. After revising the suffix, the 3D scene effect is as follows:

Note: You can choose to load the KML file in SuperMap iDesktop: open an existing scene or create a new scene, right click on the General Layers node in Layer Manager, and click Add KML Layer to add the data to the scene.