Extending an Encoder |
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.
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();
}
}
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:
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.