package com.revolsys.record.io.format.gml.type;
import javax.xml.namespace.QName;
import com.revolsys.datatype.DataType;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Lineal;
import com.revolsys.geometry.model.LinearRing;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.Polygon;
import com.revolsys.geometry.model.Polygonal;
import com.revolsys.geometry.model.Punctual;
import com.revolsys.record.io.format.gml.Gml;
import com.revolsys.record.io.format.gml.GmlRecordWriter;
import com.revolsys.record.io.format.xml.XmlWriter;
public class GmlGeometryFieldType extends AbstractGmlFieldType {
public GmlGeometryFieldType(final DataType dataType) {
super(dataType, "xs:" + dataType.getName());
}
private void coordinates(final XmlWriter out, final LineString points) {
out.startTag(Gml.COORDINATES);
final int axisCount = points.getAxisCount();
boolean first = true;
for (int i = 0; i < points.getVertexCount(); i++) {
if (first) {
first = false;
} else {
out.text(" ");
}
for (int axisIndex = 0; axisIndex < axisCount; axisIndex++) {
if (axisIndex > 0) {
out.text(",");
}
final double value = points.getCoordinate(i, axisIndex);
number(out, value);
}
}
out.endTag(Gml.COORDINATES);
}
private void coordinates(final XmlWriter out, final Point point) {
out.startTag(Gml.COORDINATES);
final int axisCount = point.getAxisCount();
for (int axisIndex = 0; axisIndex < axisCount; axisIndex++) {
if (axisIndex > 0) {
out.text(",");
}
final double value = point.getCoordinate(axisIndex);
number(out, value);
}
out.endTag(Gml.COORDINATES);
}
private void geometry(final XmlWriter out, final Object value, final boolean writeSrsName) {
if (value instanceof Geometry) {
final Geometry geometry = (Geometry)value;
if (geometry instanceof Point) {
final Point point = (Point)geometry;
point(out, point, writeSrsName);
} else if (geometry instanceof LineString) {
final LineString line = (LineString)geometry;
lineString(out, line, writeSrsName);
} else if (geometry instanceof Polygon) {
final Polygon polygon = (Polygon)geometry;
polygon(out, polygon, writeSrsName);
} else if (geometry instanceof Punctual) {
final Punctual punctual = (Punctual)geometry;
multiPoint(out, punctual, writeSrsName);
} else if (geometry instanceof Lineal) {
final Lineal lineal = (Lineal)geometry;
multiLineString(out, lineal, writeSrsName);
} else if (geometry instanceof Polygonal) {
final Polygonal polygonal = (Polygonal)geometry;
multiPolygon(out, polygonal, writeSrsName);
} else if (geometry.isGeometryCollection()) {
geometryCollection(out, geometry, writeSrsName);
}
}
}
private void geometryCollection(final XmlWriter out, final Geometry geometryCollection,
final boolean writeSrsName) {
geometryCollection(out, Gml.MULTI_GEOMETRY, Gml.GEOMETRY_MEMBER, geometryCollection,
writeSrsName);
}
private void geometryCollection(final XmlWriter out, final QName tag, final QName memberTag,
final Geometry geometryCollection, final boolean writeSrsName) {
out.startTag(tag);
srsName(out, geometryCollection, writeSrsName);
for (final Geometry geometry : geometryCollection.geometries()) {
out.startTag(memberTag);
geometry(out, geometry, false);
out.endTag(memberTag);
}
out.endTag(tag);
}
private void linearRing(final XmlWriter out, final LineString line, final boolean writeSrsName) {
out.startTag(Gml.LINEAR_RING);
final LineString points = line;
coordinates(out, points);
out.endTag(Gml.LINEAR_RING);
}
private void lineString(final XmlWriter out, final LineString line, final boolean writeSrsName) {
out.startTag(Gml.LINE_STRING);
srsName(out, line, writeSrsName);
if (!line.isEmpty()) {
final LineString points = line;
coordinates(out, points);
}
out.endTag(Gml.LINE_STRING);
}
private void multiLineString(final XmlWriter out, final Lineal lineal,
final boolean writeSrsName) {
geometryCollection(out, Gml.MULTI_LINE_STRING, Gml.LINE_STRING_MEMBER, lineal, writeSrsName);
}
private void multiPoint(final XmlWriter out, final Punctual punctual,
final boolean writeSrsName) {
geometryCollection(out, Gml.MULTI_POINT, Gml.POINT_MEMBER, punctual, writeSrsName);
}
private void multiPolygon(final XmlWriter out, final Polygonal polygonal,
final boolean writeSrsName) {
geometryCollection(out, Gml.MULTI_POLYGON, Gml.POLYGON_MEMBER, polygonal, writeSrsName);
}
public void number(final XmlWriter out, final double value) {
if (Double.isInfinite(value)) {
if (value < 0) {
out.text("-INF");
} else {
out.text("INF");
}
} else if (Double.isNaN(value)) {
out.text("NaN");
} else {
out.text(value);
}
}
private void point(final XmlWriter out, final Point point, final boolean writeSrsName) {
out.startTag(Gml.POINT);
srsName(out, point, writeSrsName);
if (!point.isEmpty()) {
coordinates(out, point);
}
out.endTag(Gml.POINT);
}
private void polygon(final XmlWriter out, final Polygon polygon, final boolean writeSrsName) {
out.startTag(Gml.POLYGON);
srsName(out, polygon, writeSrsName);
if (!polygon.isEmpty()) {
final LinearRing shell = polygon.getShell();
out.startTag(Gml.OUTER_BOUNDARY_IS);
linearRing(out, shell.toCounterClockwise(), false);
out.endTag(Gml.OUTER_BOUNDARY_IS);
for (final LinearRing hole : polygon.holes()) {
out.startTag(Gml.INNER_BOUNDARY_IS);
linearRing(out, hole.toClockwise(), false);
out.endTag(Gml.INNER_BOUNDARY_IS);
}
}
out.endTag(Gml.POLYGON);
}
private void srsName(final XmlWriter out, final Geometry geometry, final boolean writeSrsName) {
if (writeSrsName) {
final GeometryFactory factory = geometry.getGeometryFactory();
GmlRecordWriter.srsName(out, factory);
}
}
@Override
public void writeValue(final XmlWriter out, final Object value) {
super.writeValue(out, value);
}
@Override
protected void writeValueText(final XmlWriter out, final Object value) {
geometry(out, value, true);
}
}