package org.xbib.elasticsearch.common.util;
import com.spatial4j.core.shape.Rectangle;
import com.spatial4j.core.shape.Shape;
import com.spatial4j.core.shape.jts.JtsGeometry;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
/**
* Serializes {@link Shape} instances into GeoJSON format
*
* Example of the format used for points:
*
* { "type": "Point", "coordinates": [100.0, 0.0] }
*/
public class GeoJSONShapeSerializer {
private GeoJSONShapeSerializer() {
}
/**
* Serializes the given {@link Shape} as GeoJSON format into the given
* {@link XContentBuilder}
*
* @param shape Shape that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
public static void serialize(Shape shape, XContentBuilder builder) throws IOException {
if (shape instanceof JtsGeometry) {
Geometry geometry = ((JtsGeometry) shape).getGeom();
if (geometry instanceof Point) {
serializePoint((Point) geometry, builder);
} else if (geometry instanceof LineString) {
serializeLineString((LineString) geometry, builder);
} else if (geometry instanceof Polygon) {
serializePolygon((Polygon) geometry, builder);
} else if (geometry instanceof MultiPoint) {
serializeMultiPoint((MultiPoint) geometry, builder);
} else if (geometry instanceof MultiPolygon) {
serializeMulitPolygon((MultiPolygon) geometry, builder);
} else {
throw new IllegalArgumentException("Geometry type [" + geometry.getGeometryType() + "] not supported");
}
} else if (shape instanceof com.spatial4j.core.shape.Point) {
serializePoint((com.spatial4j.core.shape.Point) shape, builder);
} else if (shape instanceof Rectangle) {
serializeRectangle((Rectangle) shape, builder);
} else {
throw new IllegalArgumentException("Shape type [" + shape.getClass().getSimpleName() + "] not supported");
}
}
/**
* Serializes the given {@link Rectangle}
*
* @param rectangle Rectangle that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializeRectangle(Rectangle rectangle, XContentBuilder builder) throws IOException {
builder.field("type", "Envelope")
.startArray("coordinates")
.startArray().value(rectangle.getMinX()).value(rectangle.getMaxY()).endArray()
.startArray().value(rectangle.getMaxX()).value(rectangle.getMinY()).endArray()
.endArray();
}
/**
* Serializes the given {@link Point}
*
* @param point Point that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializePoint(Point point, XContentBuilder builder) throws IOException {
builder.field("type", "Point")
.startArray("coordinates")
.value(point.getX()).value(point.getY())
.endArray();
}
/**
* Serializes the given {@link com.spatial4j.core.shape.Point}
*
* @param point Point that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializePoint(com.spatial4j.core.shape.Point point, XContentBuilder builder) throws IOException {
builder.field("type", "Point")
.startArray("coordinates")
.value(point.getX()).value(point.getY())
.endArray();
}
/**
* Serializes the given {@link LineString}
*
* @param lineString LineString that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializeLineString(LineString lineString, XContentBuilder builder) throws IOException {
builder.field("type", "LineString")
.startArray("coordinates");
for (Coordinate coordinate : lineString.getCoordinates()) {
serializeCoordinate(coordinate, builder);
}
builder.endArray();
}
/**
* Serializes the given {@link Polygon}
*
* @param polygon Polygon that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializePolygon(Polygon polygon, XContentBuilder builder) throws IOException {
builder.field("type", "Polygon")
.startArray("coordinates");
serializePolygonCoordinates(polygon, builder);
builder.endArray();
}
/**
* Serializes the actual coordinates of the given {@link Polygon}
*
* @param polygon Polygon whose coordinates will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializePolygonCoordinates(Polygon polygon, XContentBuilder builder) throws IOException {
builder.startArray(); // start outer ring
for (Coordinate coordinate : polygon.getExteriorRing().getCoordinates()) {
serializeCoordinate(coordinate, builder);
}
builder.endArray(); // end outer ring
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
LineString interiorRing = polygon.getInteriorRingN(i);
builder.startArray();
for (Coordinate coordinate : interiorRing.getCoordinates()) {
serializeCoordinate(coordinate, builder);
}
builder.endArray();
}
}
/**
* Serializes the given {@link MultiPolygon}
*
* @param multiPolygon MultiPolygon that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializeMulitPolygon(MultiPolygon multiPolygon, XContentBuilder builder) throws IOException {
builder.field("type", "MultiPolygon")
.startArray("coordinates");
for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
builder.startArray();
serializePolygonCoordinates((Polygon) multiPolygon.getGeometryN(i), builder);
builder.endArray();
}
builder.endArray();
}
/**
* Serializes the given {@link MultiPoint}
*
* @param multiPoint MultiPoint that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializeMultiPoint(MultiPoint multiPoint, XContentBuilder builder) throws IOException {
builder.field("type", "MultiPoint")
.startArray("coordinates");
for (Coordinate coordinate : multiPoint.getCoordinates()) {
serializeCoordinate(coordinate, builder);
}
builder.endArray();
}
/**
* Serializes the given {@link Coordinate}
*
* @param coordinate Coordinate that will be serialized
* @param builder XContentBuilder it will be serialized to
* @throws IOException Thrown if an error occurs while writing to the XContentBuilder
*/
private static void serializeCoordinate(Coordinate coordinate, XContentBuilder builder) throws IOException {
builder.startArray().value(coordinate.x).value(coordinate.y).endArray();
}
}