/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ /* * Created 27.10.2005 15:33:24 by nash * * Class for creating DOM Elements containing valid GML representations of JTS geometries * * 2005 Ed Nash / Universitt Rostock * * License: GPL (see http://www.gnu.org/licenses/gpl.txt) */ package de.preagro.jts2gmldom; import com.vividsolutions.jts.geom.*; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; /** * <p>Class for creating DOM Elements containing valid GML representations of JTS geometries</p> * * <p>TODO currently doesn't do anything about reference systems</p> * * @author nash * @version 0.1 */ public class Jts2GmlDOM { //~ Static fields/initializers --------------------------------------------- /** logger for debugging purposes. */ protected static final Logger LOGGER = Logger.getLogger("de.preagro.jts2gmldom"); private static final String EMPTY_STRING = ""; public static final String EIGHT_DP_NUMBER_FORMAT = "0.########"; public static final String GML_NAMESPACE = "http://www.opengis.net/gml"; public static final String GML_PREFIX = "gml"; public static final String PREFIX_SEPARATOR = ":"; public static final String DEFAULT_LIST_SEPARATOR = " "; public static final String DEFAULT_TUPLE_SEPARATOR = ","; public static final String POINT = "Point"; public static final String POS = "pos"; public static final String LINESTRING = "LineString"; public static final String LINEARRING = "LinearRing"; public static final String POSLIST = "posList"; public static final String POLYGON = "Polygon"; public static final String EXTERIOR = "exterior"; public static final String INTERIOR = "interior"; public static final String MULTIGEOMETRY = "MultiGeometry"; public static final String GEOMETRYMEMBER = "geometryMember"; public static final String MULTICURVE = "MultiCurve"; public static final String CURVEMEMBER = "curveMember"; public static final String MULTIPOINT = "MultiPoint"; public static final String POINTMEMBER = "pointMember"; public static final String MULTISURFACE = "MultiSurface"; public static final String SURFACEMEMBER = "surfaceMember"; //~ Instance fields -------------------------------------------------------- private Document doc; //~ Constructors ----------------------------------------------------------- /** * Creates a new Jts2GmlDOM object. * * @throws ParserConfigurationException DOCUMENT ME! * @throws FactoryConfigurationError DOCUMENT ME! */ public Jts2GmlDOM() throws ParserConfigurationException, FactoryConfigurationError { super(); doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); } //~ Methods ---------------------------------------------------------------- /** * DOCUMENT ME! * * @param theGeom DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element geometryToGmlElement(final Geometry theGeom) throws DOMException { // first we need to know the type of the Geometry final int geomType = GeomTypes.classifyGeometry(theGeom); // then do the handling switch (geomType) { case GeomTypes.POINT: { return pointToGmlElement((Point)theGeom); } case GeomTypes.LINESTRING: { return lineStringToGmlElement((LineString)theGeom); } case GeomTypes.LINEARRING: { return linearRingToGmlElement((LinearRing)theGeom); } case GeomTypes.POLYGON: { return polygonToGmlElement((Polygon)theGeom); } case GeomTypes.GEOMETRYCOLLECTION: { return geometryCollectionToGmlElement((GeometryCollection)theGeom); } case GeomTypes.MULTIPOINT: { return multiPointToGmlElement((MultiPoint)theGeom); } case GeomTypes.MULTILINESTRING: { return multiLineStringToGmlElement((MultiLineString)theGeom); } case GeomTypes.MULTIPOLYGON: { return multiPolygonToGmlElement((MultiPolygon)theGeom); } case GeomTypes.UNKNOWN: default: { return null; } } } /** * DOCUMENT ME! * * @param localName DOCUMENT ME! * * @return DOCUMENT ME! */ public static String gmlQualifiedTag(final String localName) { return GML_PREFIX.concat(PREFIX_SEPARATOR).concat(localName); } /** * DOCUMENT ME! * * @param elementName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ protected Element createElement(final String elementName) throws DOMException { return doc.createElementNS(GML_NAMESPACE, gmlQualifiedTag(elementName)); } /** * DOCUMENT ME! * * @param el DOCUMENT ME! * @param text DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ protected void addTextToElement(final Element el, final String text) throws DOMException { final Node n = doc.createTextNode(text); el.appendChild(n); } /** * DOCUMENT ME! * * @param thePoint DOCUMENT ME! * * @return DOCUMENT ME! */ protected String getFormattedCoord(final Coordinate thePoint) { return getFormattedCoord(thePoint, DEFAULT_LIST_SEPARATOR); } /** * DOCUMENT ME! * * @param theCoord DOCUMENT ME! * @param separator DOCUMENT ME! * * @return DOCUMENT ME! */ protected String getFormattedCoord(final Coordinate theCoord, final String separator) { // force non-scientific notation and up to 8 decimal places (should be // enough!) // HACK: also force ENGLISH locale // TODO internationalisation: should be able to specify locale (but then // also need to sort out separators and so on for the lists based on // locale) final DecimalFormat formatter = new DecimalFormat( EIGHT_DP_NUMBER_FORMAT, new DecimalFormatSymbols(Locale.ENGLISH)); return (formatter.format(theCoord.x) + separator + formatter.format(theCoord.y) + (Double.isNaN(theCoord.z) ? "" : (separator + formatter.format(theCoord.z)))); } /** * DOCUMENT ME! * * @param theCoords DOCUMENT ME! * * @return DOCUMENT ME! */ protected String getFormattedCoordList(final Coordinate[] theCoords) { return getFormattedCoordList(theCoords, DEFAULT_TUPLE_SEPARATOR, DEFAULT_LIST_SEPARATOR); } /** * DOCUMENT ME! * * @param theCoords DOCUMENT ME! * @param tupleSeparator DOCUMENT ME! * * @return DOCUMENT ME! */ protected String getFormattedCoordList(final Coordinate[] theCoords, final String tupleSeparator) { return getFormattedCoordList(theCoords, tupleSeparator, DEFAULT_LIST_SEPARATOR); } /** * DOCUMENT ME! * * @param theCoords DOCUMENT ME! * @param tupleSeparator DOCUMENT ME! * @param listSeparator DOCUMENT ME! * * @return DOCUMENT ME! */ protected String getFormattedCoordList(final Coordinate[] theCoords, final String tupleSeparator, final String listSeparator) { String coordList = EMPTY_STRING; for (int i = 0; i < theCoords.length; i++) { coordList += ((i > 0) ? listSeparator : EMPTY_STRING) + getFormattedCoord(theCoords[i], tupleSeparator); } return coordList; } /** * DOCUMENT ME! * * @param thePoint DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element pointToGmlElement(final Point thePoint) throws DOMException { final Element pointElement = createElement(POINT); final Element posElement = createElement(POS); addTextToElement(posElement, getFormattedCoord(thePoint.getCoordinate())); pointElement.appendChild(posElement); return pointElement; } /** * DOCUMENT ME! * * @param theLineString DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element lineStringToGmlElement(final LineString theLineString) throws DOMException { return linearThingToGmlElement(theLineString, LINESTRING); } /** * DOCUMENT ME! * * @param theLinearRing DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element linearRingToGmlElement(final LinearRing theLinearRing) throws DOMException { return linearThingToGmlElement(theLinearRing, LINEARRING); } /** * DOCUMENT ME! * * @param theLinearThing DOCUMENT ME! * @param elementName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ protected Element linearThingToGmlElement(final LineString theLinearThing, final String elementName) throws DOMException { final Element lineStringElement = createElement(elementName); final Element posListElement = createElement(POSLIST); addTextToElement(posListElement, getFormattedCoordList(theLinearThing.getCoordinates())); lineStringElement.appendChild(posListElement); return lineStringElement; } /** * DOCUMENT ME! * * @param thePolygon DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element polygonToGmlElement(final Polygon thePolygon) throws DOMException { final Element polygonElement = createElement(POLYGON); polygonElement.appendChild(createMemberElement(thePolygon.getExteriorRing(), EXTERIOR)); final int numInteriors = thePolygon.getNumInteriorRing(); for (int i = 0; i < numInteriors; i++) { polygonElement.appendChild(createMemberElement(thePolygon.getInteriorRingN(i), INTERIOR)); } return polygonElement; } /** * DOCUMENT ME! * * @param theGeoms DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element geometryCollectionToGmlElement(final GeometryCollection theGeoms) throws DOMException { return collectionToGmlElement(theGeoms, MULTIGEOMETRY, GEOMETRYMEMBER); } /** * DOCUMENT ME! * * @param theGeoms DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element multiPointToGmlElement(final MultiPoint theGeoms) throws DOMException { return collectionToGmlElement(theGeoms, MULTIPOINT, POINTMEMBER); } /** * DOCUMENT ME! * * @param theGeoms DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element multiLineStringToGmlElement(final MultiLineString theGeoms) throws DOMException { return collectionToGmlElement(theGeoms, MULTICURVE, CURVEMEMBER); } /** * DOCUMENT ME! * * @param theGeoms DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ public Element multiPolygonToGmlElement(final MultiPolygon theGeoms) throws DOMException { return collectionToGmlElement(theGeoms, MULTISURFACE, SURFACEMEMBER); } /** * DOCUMENT ME! * * @param theGeoms DOCUMENT ME! * @param elementName DOCUMENT ME! * @param associationName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws DOMException DOCUMENT ME! */ protected Element collectionToGmlElement(final GeometryCollection theGeoms, final String elementName, final String associationName) throws DOMException { final Element collectionElement = createElement(elementName); final int numGeoms = theGeoms.getNumGeometries(); for (int i = 0; i < numGeoms; i++) { collectionElement.appendChild(createMemberElement(theGeoms.getGeometryN(i), associationName)); } return collectionElement; } /** * DOCUMENT ME! * * @param theGeom DOCUMENT ME! * @param associationName DOCUMENT ME! * * @return DOCUMENT ME! */ protected Element createMemberElement(final Geometry theGeom, final String associationName) { final Element geometryElement = geometryToGmlElement(theGeom); final Element associationElement = createElement(associationName); associationElement.appendChild(geometryElement); return associationElement; } //~ Inner Classes ---------------------------------------------------------- /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ private static class GeomTypes { //~ Static fields/initializers ----------------------------------------- public static final int UNKNOWN = 0; public static final String POINT_NAME = "Point"; public static final int POINT = 10; public static final String LINESTRING_NAME = "LineString"; public static final int LINESTRING = 20; public static final String LINEARRING_NAME = "LinearRing"; public static final int LINEARRING = 21; public static final String POLYGON_NAME = "Polygon"; public static final int POLYGON = 30; public static final String GEOMETRYCOLLECTION_NAME = "GeometryCollection"; public static final int GEOMETRYCOLLECTION = 40; public static final String MULTIPOINT_NAME = "MultiPoint"; public static final int MULTIPOINT = 41; public static final String MULTILINESTRING_NAME = "MultiLineString"; public static final int MULTILINESTRING = 42; public static final String MULTIPOLYGON_NAME = "MultiPolygon"; public static final int MULTIPOLYGON = 43; //~ Methods ------------------------------------------------------------ /** * DOCUMENT ME! * * @param theGeom DOCUMENT ME! * * @return DOCUMENT ME! */ public static int classifyGeometry(final Geometry theGeom) { final String geomType = theGeom.getGeometryType(); if (geomType.equals(POINT_NAME)) { return POINT; } else if (geomType.equals(LINESTRING_NAME)) { return LINESTRING; } else if (geomType.equals(LINEARRING_NAME)) { return LINEARRING; } else if (geomType.equals(POLYGON_NAME)) { return POLYGON; } else if (geomType.equals(GEOMETRYCOLLECTION_NAME)) { return GEOMETRYCOLLECTION; } else if (geomType.equals(MULTIPOINT_NAME)) { return MULTIPOINT; } else if (geomType.equals(MULTILINESTRING_NAME)) { return MULTILINESTRING; } else if (geomType.equals(MULTIPOLYGON_NAME)) { return MULTIPOLYGON; } else { return UNKNOWN; } } } }