package com.revolsys.record.io.format.esri.gdb.xml.type;
import com.revolsys.datatype.DataType;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Lineal;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.Polygon;
import com.revolsys.record.io.format.esri.gdb.xml.model.enums.FieldType;
import com.revolsys.record.io.format.xml.XmlWriter;
import com.revolsys.record.io.format.xml.XsiConstants;
public class XmlGeometryFieldType extends AbstractEsriGeodatabaseXmlFieldType {
public XmlGeometryFieldType(final FieldType esriFieldType, final DataType dataType) {
super(dataType, "xs:" + dataType.getName(), esriFieldType);
}
@Override
public int getFixedLength() {
return 0;
}
@Override
protected String getType(final Object value) {
if (value instanceof Point) {
return POINT_N_TYPE;
} else if (value instanceof Lineal) {
return POLYLINE_N_TYPE;
} else if (value instanceof Polygon) {
return POLYGON_N_TYPE;
}
return null;
}
private void writeLineString(final XmlWriter out, final LineString line) {
final boolean hasZ = line.getAxisCount() > 2;
out.element(HAS_ID, false);
out.element(HAS_Z, hasZ);
out.element(HAS_M, false);
out.startTag(PATH_ARRAY);
out.attribute(XsiConstants.TYPE, PATH_ARRAY_TYPE);
writePath(out, line, hasZ);
out.endTag(PATH_ARRAY);
}
private void writeMultiLineString(final XmlWriter out, final Lineal multiLine) {
final boolean hasZ;
if (multiLine.isEmpty()) {
hasZ = false;
} else {
final LineString points = (LineString)multiLine.getGeometry(0);
hasZ = points.getAxisCount() > 2;
}
out.element(HAS_ID, false);
out.element(HAS_Z, hasZ);
out.element(HAS_M, false);
out.startTag(PATH_ARRAY);
out.attribute(XsiConstants.TYPE, PATH_ARRAY_TYPE);
for (int i = 0; i < multiLine.getGeometryCount(); i++) {
final LineString line = (LineString)multiLine.getGeometry(i);
writePath(out, line, hasZ);
}
out.endTag(PATH_ARRAY);
}
public void writePath(final XmlWriter out, final LineString line, final boolean hasZ) {
out.startTag(PATH);
out.attribute(XsiConstants.TYPE, PATH_TYPE);
writePointArray(out, line, hasZ);
out.endTag(PATH);
}
private void writePoint(final XmlWriter out, final Point point) {
final boolean hasZ = point.getAxisCount() > 2;
writePoint(out, point, hasZ);
}
public void writePoint(final XmlWriter out, final Point coordinates, final boolean hasZ) {
out.element(X, coordinates.getX());
out.element(Y, coordinates.getY());
if (hasZ) {
out.element(Z, coordinates.getZ());
}
}
public void writePointArray(final XmlWriter out, final LineString line, final boolean hasZ) {
out.startTag(POINT_ARRAY);
out.attribute(XsiConstants.TYPE, POINT_ARRAY_TYPE);
final int vertexCount = line.getVertexCount();
for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
final double x = line.getX(vertexIndex);
final double y = line.getY(vertexIndex);
out.startTag(POINT);
out.attribute(XsiConstants.TYPE, POINT_N_TYPE);
out.element(X, x);
out.element(Y, y);
if (hasZ) {
out.element(Z, line.getZ(vertexIndex));
}
out.endTag(POINT);
}
out.endTag(POINT_ARRAY);
}
private void writePolygon(final XmlWriter out, final Polygon polygon) {
final boolean hasZ;
final LineString exteriorRing = polygon.getShell();
final LineString points = exteriorRing;
hasZ = points.getAxisCount() > 2;
out.element(HAS_ID, false);
out.element(HAS_Z, hasZ);
out.element(HAS_M, false);
out.startTag(RING_ARRAY);
out.attribute(XsiConstants.TYPE, RING_ARRAY_TYPE);
writeRing(out, exteriorRing, hasZ);
for (int i = 0; i < polygon.getHoleCount(); i++) {
final LineString interiorRing = polygon.getHole(i);
writeRing(out, interiorRing, hasZ);
}
out.endTag(RING_ARRAY);
}
private void writeRing(final XmlWriter out, final LineString line, final boolean hasZ) {
out.startTag(RING);
out.attribute(XsiConstants.TYPE, RING_TYPE);
writePointArray(out, line, hasZ);
out.endTag(RING);
}
@Override
protected void writeValueText(final XmlWriter out, final Object value) {
if (value instanceof Point) {
final Point point = (Point)value;
writePoint(out, point);
} else if (value instanceof LineString) {
final LineString line = (LineString)value;
writeLineString(out, line);
} else if (value instanceof Polygon) {
final Polygon polygon = (Polygon)value;
writePolygon(out, polygon);
} else if (value instanceof Lineal) {
final Lineal multiLine = (Lineal)value;
writeMultiLineString(out, multiLine);
}
}
}