package com.revolsys.record.io.format.kml;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import com.revolsys.geometry.model.BoundingBox;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.LinearRing;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.Polygon;
import com.revolsys.io.StringBuilderWriter;
import com.revolsys.record.io.format.xml.XmlWriter;
import com.revolsys.util.Property;
import com.revolsys.util.UrlUtil;
import com.revolsys.util.number.Doubles;
public class KmlXmlWriter extends XmlWriter implements Kml22Constants {
public static void append(final StringBuilder buffer, final Geometry geometry) {
final KmlXmlWriter writer = new KmlXmlWriter(new StringBuilderWriter(buffer), false);
writer.writeGeometry(geometry, 2);
writer.close();
}
public KmlXmlWriter(final OutputStream out) {
super(out);
}
public KmlXmlWriter(final OutputStream out, final boolean useNamespaces) {
super(out, useNamespaces);
}
public KmlXmlWriter(final Writer out) {
super(out);
}
public KmlXmlWriter(final Writer out, final boolean useNamespaces) {
super(out, useNamespaces);
}
public void write(final LineString points) {
startTag(Kml22Constants.COORDINATES);
final int vertexCount = points.getVertexCount();
final int axisCount = points.getAxisCount();
for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
if (vertexIndex > 0) {
write(' ');
}
for (int axisIndex = 0; axisIndex < axisCount; axisIndex++) {
if (axisIndex > 0) {
write(',');
}
write(String.valueOf(points.getCoordinate(vertexIndex, axisIndex)));
}
}
endTag();
}
public void writeCoordinates(final Point point) {
startTag(Kml22Constants.COORDINATES);
if (point != null && !point.isEmpty()) {
for (int axisIndex = 0; axisIndex < point.getAxisCount(); axisIndex++) {
if (axisIndex > 0) {
write(',');
}
write(String.valueOf(point.getCoordinate(axisIndex)));
}
}
endTag(Kml22Constants.COORDINATES);
}
public void writeData(final String name, final Object value) {
if (value != null) {
startTag(DATA);
attribute(NAME, name);
element(VALUE, value);
endTag();
}
}
public void writeExtendedData(final Map<String, ? extends Object> data) {
boolean hasValues = false;
for (final Entry<String, ? extends Object> entry : data.entrySet()) {
final String fieldName = entry.getKey();
final Object value = entry.getValue();
if (!(value instanceof Geometry)) {
if (value != null) {
final String stringValue = value.toString();
if (Property.hasValue(stringValue)) {
if (!hasValues) {
hasValues = true;
startTag(EXTENDED_DATA);
}
startTag(DATA);
attribute(NAME, fieldName);
element(VALUE, value);
endTag(DATA);
}
}
}
}
if (hasValues) {
endTag(EXTENDED_DATA);
}
}
public void writeGeometry(final Geometry geometry, final int axisCount) {
if (geometry != null) {
final int numGeometries = geometry.getGeometryCount();
if (numGeometries > 1) {
startTag(Kml22Constants.MULTI_GEOMETRY);
for (int i = 0; i < numGeometries; i++) {
writeGeometry(geometry.getGeometry(i), axisCount);
}
endTag();
} else {
final Geometry geoGraphicsGeom = geometry.convertGeometry(
GeometryFactory.floating(Kml22Constants.COORDINATE_SYSTEM_ID, axisCount));
if (geoGraphicsGeom instanceof Point) {
final Point point = (Point)geoGraphicsGeom;
writePoint(point);
} else if (geoGraphicsGeom instanceof LinearRing) {
final LinearRing line = (LinearRing)geoGraphicsGeom;
writeLinearRing(line);
} else if (geoGraphicsGeom instanceof LineString) {
final LineString line = (LineString)geoGraphicsGeom;
writeLineString(line);
} else if (geoGraphicsGeom instanceof Polygon) {
final Polygon polygon = (Polygon)geoGraphicsGeom;
writePolygon(polygon);
} else if (geoGraphicsGeom.isGeometryCollection()) {
writeMultiGeometry(geoGraphicsGeom, axisCount);
}
}
}
}
public void writeLatLonBox(final com.revolsys.geometry.model.BoundingBox envelope) {
startTag(LAT_LON_BOX);
element(NORTH, envelope.getMaxY());
element(SOUTH, envelope.getMinY());
element(WEST, envelope.getMinX());
element(EAST, envelope.getMaxX());
endTag();
}
public void writeLinearRing(final LineString ring) {
startTag(Kml22Constants.LINEAR_RING);
final LineString coordinateSequence = ring;
write(coordinateSequence);
endTag();
}
public void writeLineString(final LineString line) {
startTag(Kml22Constants.LINE_STRING);
final LineString coordinateSequence = line;
write(coordinateSequence);
endTag();
}
public void writeMultiGeometry(final Geometry collection, final int axisCount) {
startTag(Kml22Constants.MULTI_GEOMETRY);
for (int i = 0; i < collection.getGeometryCount(); i++) {
final Geometry geometry = collection.getGeometry(i);
writeGeometry(geometry, axisCount);
}
endTag(Kml22Constants.MULTI_GEOMETRY);
}
public void writeNetworkLink(final com.revolsys.geometry.model.BoundingBox envelope,
final String name, final Integer minLod, final Integer maxLod, final String href) {
startTag(NETWORK_LINK);
if (name != null) {
element(NAME, name);
}
writeRegion(envelope, minLod, maxLod);
startTag(LINK);
element(HREF, href);
element(VIEW_REFRESH_MODE, "onRegion");
endTag();
endTag();
}
public void writePlacemark(final Geometry geometry, final String name, final String styleUrl) {
startTag(PLACEMARK);
if (name != null) {
element(NAME, name);
}
if (styleUrl != null) {
element(STYLE_URL, styleUrl);
}
writeGeometry(geometry, 2);
endTag();
}
public void writePlacemarkLineString(final com.revolsys.geometry.model.BoundingBox envelope,
final String name, final String styleUrl) {
startTag(PLACEMARK);
if (name != null) {
element(NAME, name);
}
if (styleUrl != null) {
element(STYLE_URL, styleUrl);
}
startTag(LINE_STRING);
startTag(COORDINATES);
final double maxY = envelope.getMaxY();
final double minY = envelope.getMinY();
final double maxX = envelope.getMaxX();
final double minX = envelope.getMinX();
write(Double.toString(minX));
write(',');
write(Double.toString(minY));
write(' ');
write(Double.toString(maxX));
write(',');
write(Double.toString(minY));
write(' ');
write(Double.toString(maxX));
write(',');
write(Double.toString(maxY));
write(' ');
write(Double.toString(minX));
write(',');
write(Double.toString(maxY));
write(' ');
write(Double.toString(minX));
write(',');
write(Double.toString(minY));
endTag();
endTag();
endTag();
}
public void writePlacemarkLineString(final LineString lineString, final String name,
final String styleUrl) {
startTag(PLACEMARK);
if (name != null) {
element(NAME, name);
}
if (styleUrl != null) {
element(STYLE_URL, styleUrl);
}
writeLineString(lineString);
endTag();
}
public void writePlacemarkLineString(final Polygon polygon, final String name,
final String styleUrl) {
startTag(PLACEMARK);
if (name != null) {
element(NAME, name);
}
if (styleUrl != null) {
element(STYLE_URL, styleUrl);
}
final LineString exteriorRing = polygon.getShell();
writeLineString(exteriorRing);
endTag();
}
public void writePlacemarkPoint(final BoundingBox boundingBox, final String name,
final String styleUrl) {
startTag(PLACEMARK);
if (name != null) {
element(NAME, name);
}
if (styleUrl != null) {
element(STYLE_URL, styleUrl);
}
startTag(POINT);
startTag(COORDINATES);
final double x = boundingBox.getCentreX();
final double y = boundingBox.getCentreY();
write(Doubles.toString(x));
write(',');
write(Doubles.toString(y));
endTag();
endTag();
endTag();
}
public void writePlacemarkPolygon(final Polygon polygon, final String name,
final String styleUrl) {
startTag(PLACEMARK);
if (name != null) {
element(NAME, name);
}
if (styleUrl != null) {
element(STYLE_URL, styleUrl);
}
writePolygon(polygon);
endTag();
}
public void writePoint(final Point point) {
startTag(Kml22Constants.POINT);
writeCoordinates(point);
endTag(Kml22Constants.POINT);
}
public void writePolygon(final Polygon polygon) {
startTag(Kml22Constants.POLYGON);
if (!polygon.isEmpty()) {
startTag(Kml22Constants.OUTER_BOUNDARY_IS);
writeLinearRing(polygon.getShell());
endTag();
for (int i = 0; i < polygon.getHoleCount(); i++) {
startTag(Kml22Constants.INNER_BOUNDARY_IS);
final LineString ring = polygon.getHole(i);
writeLinearRing(ring);
endTag();
}
}
endTag();
}
public void writeRegion(final com.revolsys.geometry.model.BoundingBox envelope,
final Integer minLod, final Integer maxLod) {
startTag(REGION);
startTag(LAT_LON_ALT_BOX);
element(NORTH, envelope.getMaxY());
element(SOUTH, envelope.getMinY());
element(EAST, envelope.getMaxX());
element(WEST, envelope.getMinX());
endTag();
if (minLod != null || maxLod != null) {
startTag(LOD);
if (minLod != null) {
element(MIN_LOD_PIXELS, minLod);
element(MAX_LOD_PIXELS, maxLod);
}
endTag();
}
endTag();
}
public void writeWmsGroundOverlay(final com.revolsys.geometry.model.BoundingBox envelope,
final String baseUrl, final String name) {
startTag(GROUND_OVERLAY);
if (name != null) {
element(NAME, name);
}
writeLatLonBox(envelope);
startTag(ICON);
final Map<String, String> parameters = Collections.singletonMap("BBOX", envelope.getMinX() + ","
+ envelope.getMinY() + "," + envelope.getMaxX() + "," + envelope.getMaxY());
element(HREF, UrlUtil.getUrl(baseUrl, parameters));
endTag();
endTag();
}
}