/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.xacml.geoxacml.attr; import java.util.List; import java.util.Map; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; /** * * Class for supporting GML2 encoding and GML2 Parsing * * @author Christian Mueller * */ public class GML3Support extends GMLSupport { public final static String GML_POINT = "http://www.opengis.net/gml#Point"; public final static String GML_LINESTRING = "http://www.opengis.net/gml#LineString"; public final static String GML_LINEARRING = "http://www.opengis.net/gml#LinearRing"; public final static String GML_POLYGON = "http://www.opengis.net/gml#Polygon"; public final static String GML_ENVELOPE = "http://www.opengis.net/gml#Envelope"; public final static String GML_MULTIPOINT = "http://www.opengis.net/gml#MultiPoint"; public final static String GML_MULTICURVE = "http://www.opengis.net/gml#MultiCurve"; public final static String GML_MULTISURFACE = "http://www.opengis.net/gml#MultiSurface"; public final static GML3Support Singleton = new GML3Support(); GeometryAttribute buildFromGML(Node gmlNode) throws Exception { NamedNodeMap attrMap = gmlNode.getAttributes(); Node n = attrMap.getNamedItem("gid"); String gid = n == null ? null : n.getTextContent(); n = attrMap.getNamedItem("srsName"); String srsName = n == null ? null : n.getTextContent(); n = attrMap.getNamedItem("srsDimension"); int srsDimension = n == null ? 2 : Integer.valueOf(n.getTextContent()); if ("Point".equals(gmlNode.getLocalName())) { Point p = parsePoint(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(p, srsName, gid, GMLVersion.Version3, GML_POINT); attr.setSrsDimension(srsDimension); return attr; } if ("LineString".equals(gmlNode.getLocalName())) { LineString ls = parseLineString(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(ls, srsName, gid, GMLVersion.Version3, GML_LINESTRING); attr.setSrsDimension(srsDimension); return attr; } if ("LinearRing".equals(gmlNode.getLocalName())) { LinearRing lr = parseLinearRing(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(lr, srsName, gid, GMLVersion.Version3, GML_LINEARRING); attr.setSrsDimension(srsDimension); return attr; } if ("Polygon".equals(gmlNode.getLocalName())) { Polygon poly = parsePolygon(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(poly, srsName, gid, GMLVersion.Version3, GML_POLYGON); attr.setSrsDimension(srsDimension); return attr; } if ("Envelope".equals(gmlNode.getLocalName())) { Polygon poly = parseEnvelope(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(poly, srsName, gid, GMLVersion.Version3, GML_ENVELOPE); attr.setSrsDimension(srsDimension); return attr; } if ("MultiPoint".equals(gmlNode.getLocalName())) { MultiPoint mp = parseMultiPoint(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(mp, srsName, gid, GMLVersion.Version3, GML_MULTIPOINT); attr.setSrsDimension(srsDimension); return attr; } if ("MultiCurve".equals(gmlNode.getLocalName())) { MultiLineString mp = parseMultiCurve(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(mp, srsName, gid, GMLVersion.Version3, GML_MULTICURVE); attr.setSrsDimension(srsDimension); return attr; } if ("MultiSurface".equals(gmlNode.getLocalName())) { MultiPolygon mp = parseMultiSurface(gmlNode, srsDimension); GeometryAttribute attr = new GeometryAttribute(mp, srsName, gid, GMLVersion.Version3, GML_MULTISURFACE); attr.setSrsDimension(srsDimension); return attr; } return null; } void encodeASGML(GeometryAttribute attr, StringBuffer buff) { Map<String, String> abstractGeometryAttributeMap = abstractGeometryAttribueMap(attr); abstractGeometryAttributeMap.put("xmlns:" + GMLNS_PREFIX, GMLNS); if (GML_POINT.equals(attr.getGmlType())) encodePoint((Point) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr .getSrsDimension()); if (GML_LINESTRING.equals(attr.getGmlType())) encodeLineString((LineString) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr.getSrsDimension()); if (GML_LINEARRING.equals(attr.getGmlType())) encodeLinearRing((LinearRing) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr.getSrsDimension()); if (GML_POLYGON.equals(attr.getGmlType())) encodePolygon((Polygon) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr .getSrsDimension()); if (GML_ENVELOPE.equals(attr.getGmlType())) encodeEnvelope((Polygon) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr .getSrsDimension()); if (GML_MULTIPOINT.equals(attr.getGmlType())) encodeMultiPoint((MultiPoint) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr.getSrsDimension()); if (GML_MULTICURVE.equals(attr.getGmlType())) encodeMultiCurve((MultiLineString) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr.getSrsDimension()); if (GML_MULTISURFACE.equals(attr.getGmlType())) encodeMultiSurface((MultiPolygon) attr.getGeometry(), buff, abstractGeometryAttributeMap, attr.getSrsDimension()); } private double[] parseDoubleList(Node node) throws GMLException { final String anyBlankSeq = "\\s+"; final String singleSpace = " "; String text = node.getTextContent().replaceAll(anyBlankSeq, singleSpace).trim(); String[] values = text.split(" +"); double[] doubles = new double[values.length]; for (int i = 0; i < values.length; i++) doubles[i] = Double.valueOf(values[i]); return doubles; } public LinearRing parseLinearRing(Node node, int srsDimension) throws GMLException { List<Node> coordinates = getChildren(node, "pos"); if (!coordinates.isEmpty() && (coordinates.size() >= 4)) { Coordinate[] coordArray = new Coordinate[coordinates.size()]; for (int i = 0; i < coordinates.size(); i++) { coordArray[i] = parseDirectPosition(coordinates.get(i), srsDimension); } return gf.createLinearRing(coordArray); } if (!coordinates.isEmpty()) { throw new GMLException(LINEARRING_ERROR); } Node coords = getChild(node, "posList"); if (coords != null) { CoordinateSequence cs = parseDirectPositionList(coords, srsDimension); if (cs.size() < 4) { throw new GMLException(LINEARRING_ERROR); } return gf.createLinearRing(cs); } // try GML2 stuff LinearRing lr = parseLinearRingGML2(node); if (lr == null) throw new GMLException( "Could not find \"pos\",\"posList\",\"coords\" or \"coordinates\" for LinearRing"); return lr; } public LineString parseLineString(Node node, int srsDimension) throws GMLException { List<Node> coordinates = getChildren(node, "pos"); if (!coordinates.isEmpty() && (coordinates.size() >= 2)) { Coordinate[] coordArray = new Coordinate[coordinates.size()]; for (int i = 0; i < coordinates.size(); i++) { coordArray[i] = parseDirectPosition(coordinates.get(i), srsDimension); } return gf.createLineString(coordArray); } if (!coordinates.isEmpty()) { throw new GMLException(LINESTRING_ERROR); } Node coords = getChild(node, "posList"); if (coords != null) { CoordinateSequence cs = parseDirectPositionList(coords, srsDimension); if (cs.size() < 2) { throw new GMLException(LINESTRING_ERROR); } return gf.createLineString(cs); } // try GML2 stuff LineString ls = parseLineStringGML2(node); if (ls == null) throw new GMLException( "Could not find \"pos\",\"posList\",\"coords\" or \"coordinates\" for LinearRing"); return ls; } protected Coordinate parseDirectPosition(Node node, int srsDimension) throws GMLException { double[] oords = parseDoubleList(node); if (srsDimension == 1) return new Coordinate(oords[0], Double.NaN); if (srsDimension == 2) return new Coordinate(oords[0], oords[1]); if (srsDimension == 3) return new Coordinate(oords[0], oords[1], oords[2]); throw new GMLException("Cannot parse DirectPosition"); } protected void encodeDirectPostion(Coordinate c, StringBuffer buff, int srsDimension) { encodeStartTag("pos", buff, null); buff.append(c.x); if (srsDimension == 2) buff.append(" ").append(c.y); if (srsDimension == 3) buff.append(" ").append(c.z); encodeEndTag("pos", buff); } protected void encodeDirectPositionList(CoordinateSequence s, StringBuffer buff, int srsDimension) { encodeStartTag("posList", buff, null); for (int i = 0; i < s.size(); i++) { Coordinate c = s.getCoordinate(i); if (i > 0) buff.append(" "); buff.append(c.x); if (srsDimension == 2) buff.append(" ").append(c.y); if (srsDimension == 3) buff.append(" ").append(c.z); } encodeEndTag("posList", buff); } protected CoordinateSequence parseDirectPositionList(Node node, int srsDimension) throws GMLException { double[] values = parseDoubleList(node); // NamedNodeMap attrMap = node.getAttributes(); // int srsDimension = 2; // Node attrNode = attrMap.getNamedItem("srsDimension"); // if (attrNode != null) { // srsDimension = Integer.valueOf(attrNode.getTextContent()); // } // // if (srsDimension <1 || srsDimension > 3) { // throw new GMLException("crsDimenstion must be one of 1 or 2 or 3"); // } // // int coordinatesCount; // // attrNode = attrMap.getNamedItem("count"); // if (attrNode != null) { // coordinatesCount = Integer.valueOf(attrNode.getTextContent()); // } else { // coordinatesCount= values.length / srsDimension; // } int coordinatesCount = values.length / srsDimension; Coordinate[] array = new Coordinate[coordinatesCount]; for (int i = 0; i < coordinatesCount; i++) { int offset = i * srsDimension; if (srsDimension == 1) array[i] = new Coordinate(values[offset], Double.NaN, Double.NaN); if (srsDimension == 2) array[i] = new Coordinate(values[offset], values[offset + 1], Double.NaN); if (srsDimension == 3) array[i] = new Coordinate(values[offset], values[offset + 1], values[offset + 2]); } return csFactory.create(array); } public Point parsePoint(Node node, int srsDimension) throws GMLException { Node coord = getChild(node, "pos"); if (coord != null) { Coordinate c = parseDirectPosition(coord, srsDimension); return gf.createPoint(c); } // try the depricated GML2 stuff // try GML2 stuff Point p = parsePointGML2(node); if (p == null) throw new GMLException("Could not find a \"pos\", \"coord\" or \"coordinates\" element"); return p; } public Polygon parsePolygon(Node node, int srsDimension) throws GMLException { Node outer = getChild(node, "exterior"); Node lr = getChild(outer, "LinearRing"); LinearRing extRing = parseLinearRing(lr, srsDimension); List<Node> innerList = getChildren(node, "interior"); LinearRing[] innerRings = new LinearRing[innerList.size()]; for (int i = 0; i < innerRings.length; i++) { lr = getChild(innerList.get(i), "LinearRing"); innerRings[i] = parseLinearRing(lr, srsDimension); } return gf.createPolygon(extRing, innerRings); } protected void encodePoint(Point p, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("Point", buff, abstractGeometryAttributeMap); encodeDirectPostion(p.getCoordinate(), buff, srsDimension); encodeEndTag("Point", buff); } public void encodeLineString(LineString ls, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("LineString", buff, abstractGeometryAttributeMap); encodeDirectPositionList(ls.getCoordinateSequence(), buff, srsDimension); encodeEndTag("LineString", buff); } public void encodeLinearRing(LinearRing lr, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("LinearRing", buff, abstractGeometryAttributeMap); encodeDirectPositionList(lr.getCoordinateSequence(), buff, srsDimension); encodeEndTag("LinearRing", buff); } public void encodePolygon(Polygon poly, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("Polygon", buff, abstractGeometryAttributeMap); encodeStartTag("exterior", buff, null); encodeStartTag("LinearRing", buff, null); encodeDirectPositionList(poly.getExteriorRing().getCoordinateSequence(), buff, srsDimension); encodeEndTag("LinearRing", buff); encodeEndTag("exterior", buff); int countInner = poly.getNumInteriorRing(); for (int i = 0; i < countInner; i++) { encodeStartTag("interior", buff, null); encodeStartTag("LinearRing", buff, null); encodeDirectPositionList(poly.getInteriorRingN(i).getCoordinateSequence(), buff, srsDimension); encodeEndTag("LinearRing", buff); encodeEndTag("interior", buff); } encodeEndTag("Polygon", buff); } public Polygon parseEnvelope(Node node, int srsDimension) throws GMLException { List<Node> coordinates = getChildren(node, "pos"); if (!coordinates.isEmpty() && (coordinates.size() == 2)) { Node n1 = (Node) coordinates.get(0); Node n2 = (Node) coordinates.get(1); Coordinate c1 = parseDirectPosition(n1, srsDimension); Coordinate c2 = parseDirectPosition(n2, srsDimension); return toGeometry(new Envelope(c1.x, c2.x, c1.y, c2.y)); } if (!coordinates.isEmpty()) { throw new GMLException("Envelope can have only two coordinates"); } Node lower = getChild(node, "lowerCorner"); Node upper = getChild(node, "upperCorner"); if (lower != null && upper != null) { Coordinate c1 = parseDirectPosition(lower, srsDimension); Coordinate c2 = parseDirectPosition(upper, srsDimension); return toGeometry(new Envelope(c1.x, c2.x, c1.y, c2.y)); } throw new GMLException("Could not find direct positions for envelope"); } public void encodeEnvelope(Polygon poly, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("Envelope", buff, abstractGeometryAttributeMap); Envelope env = poly.getEnvelopeInternal(); encodeDirectPostion(new Coordinate(env.getMinX(), env.getMinY()), buff, srsDimension); encodeDirectPostion(new Coordinate(env.getMaxX(), env.getMaxY()), buff, srsDimension); encodeEndTag("Envelope", buff); } public MultiPoint parseMultiPoint(Node node, int srsDimension) throws GMLException { Node pointMembers = getChild(node, "pointMembers"); if (pointMembers != null) { List<Node> pointMemberList = getChildren(pointMembers, "Point"); Point[] array = new Point[pointMemberList.size()]; for (int i = 0; i < pointMemberList.size(); i++) { array[i] = parsePoint(pointMemberList.get(i), srsDimension); } return gf.createMultiPoint(array); } List<Node> pointMemberList = getChildren(node, "pointMember"); Point[] array = new Point[pointMemberList.size()]; for (int i = 0; i < pointMemberList.size(); i++) { Node pointNode = getChild(pointMemberList.get(i), "Point"); array[i] = parsePoint(pointNode, srsDimension); } return gf.createMultiPoint(array); } public MultiLineString parseMultiCurve(Node node, int srsDimension) throws GMLException { Node curveMembers = getChild(node, "curveMembers"); if (curveMembers != null) { List<Node> lsMemberList = getChildren(curveMembers, "LineString"); LineString[] array = new LineString[lsMemberList.size()]; for (int i = 0; i < lsMemberList.size(); i++) { array[i] = parseLineString(lsMemberList.get(i), srsDimension); } return gf.createMultiLineString(array); } List<Node> curveMemberList = getChildren(node, "curveMember"); LineString[] array = new LineString[curveMemberList.size()]; for (int i = 0; i < curveMemberList.size(); i++) { Node lsNode = getChild(curveMemberList.get(i), "LineString"); array[i] = parseLineString(lsNode, srsDimension); } return gf.createMultiLineString(array); } public MultiPolygon parseMultiSurface(Node node, int srsDimension) throws GMLException { Node surfaceMembers = getChild(node, "surfaceMembers"); if (surfaceMembers != null) { List<Node> polyMemberList = getChildren(surfaceMembers, "Polygon"); Polygon[] array = new Polygon[polyMemberList.size()]; for (int i = 0; i < polyMemberList.size(); i++) { array[i] = parsePolygon(polyMemberList.get(i), srsDimension); } return gf.createMultiPolygon(array); } List<Node> surfaceMemberList = getChildren(node, "surfaceMember"); Polygon[] array = new Polygon[surfaceMemberList.size()]; for (int i = 0; i < surfaceMemberList.size(); i++) { Node polygonNode = getChild(surfaceMemberList.get(i), "Polygon"); array[i] = parsePolygon(polygonNode, srsDimension); } return gf.createMultiPolygon(array); } public void encodeMultiPoint(MultiPoint mp, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("MultiPoint", buff, abstractGeometryAttributeMap); encodeStartTag("pointMembers", buff, null); for (int i = 0; i < mp.getNumGeometries(); i++) { Point p = (Point) mp.getGeometryN(i); encodePoint(p, buff, null, srsDimension); } encodeEndTag("pointMembers", buff); encodeEndTag("MultiPoint", buff); } public void encodeMultiCurve(MultiLineString mls, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("MultiCurve", buff, abstractGeometryAttributeMap); encodeStartTag("curveMembers", buff, null); for (int i = 0; i < mls.getNumGeometries(); i++) { LineString ls = (LineString) mls.getGeometryN(i); encodeLineString(ls, buff, null, srsDimension); } encodeEndTag("curveMembers", buff); encodeEndTag("MultiCurve", buff); } public void encodeMultiSurface(MultiPolygon mp, StringBuffer buff, Map<String, String> abstractGeometryAttributeMap, int srsDimension) { encodeStartTag("MultiSurface", buff, abstractGeometryAttributeMap); encodeStartTag("surfaceMembers", buff, null); for (int i = 0; i < mp.getNumGeometries(); i++) { Polygon p = (Polygon) mp.getGeometryN(i); encodePolygon(p, buff, null, srsDimension); } encodeEndTag("surfaceMembers", buff); encodeEndTag("MultiSurface", buff); } }