0001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/model/spatialschema/GMLGeometryAdapter.java $
0002: /*---------------- FILE HEADER ------------------------------------------
0003:
0004: This file is part of deegree.
0005: Copyright (C) 2001-2008 by:
0006: EXSE, Department of Geography, University of Bonn
0007: http://www.giub.uni-bonn.de/deegree/
0008: lat/lon GmbH
0009: http://www.lat-lon.de
0010:
0011: This library is free software; you can redistribute it and/or
0012: modify it under the terms of the GNU Lesser General Public
0013: License as published by the Free Software Foundation; either
0014: version 2.1 of the License, or (at your option) any later version.
0015:
0016: This library is distributed in the hope that it will be useful,
0017: but WITHOUT ANY WARRANTY; without even the implied warranty of
0018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0019: Lesser General Public License for more details.
0020:
0021: You should have received a copy of the GNU Lesser General Public
0022: License along with this library; if not, write to the Free Software
0023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0024:
0025: Contact:
0026:
0027: Andreas Poth
0028: lat/lon GmbH
0029: Aennchenstr. 19
0030: 53177 Bonn
0031: Germany
0032: E-Mail: poth@lat-lon.de
0033:
0034: Klaus Greve
0035: Department of Geography
0036: University of Bonn
0037: Meckenheimer Allee 166
0038: 53115 Bonn
0039: Germany
0040: E-Mail: klaus.greve@uni-bonn.de
0041:
0042:
0043: ---------------------------------------------------------------------------*/
0044: package org.deegree.model.spatialschema;
0045:
0046: import java.io.ByteArrayOutputStream;
0047: import java.io.OutputStream;
0048: import java.io.PrintWriter;
0049: import java.io.StringReader;
0050: import java.rmi.RemoteException;
0051: import java.util.ArrayList;
0052: import java.util.HashMap;
0053: import java.util.List;
0054: import java.util.Map;
0055: import java.util.StringTokenizer;
0056:
0057: import org.deegree.framework.log.ILogger;
0058: import org.deegree.framework.log.LoggerFactory;
0059: import org.deegree.framework.util.StringTools;
0060: import org.deegree.framework.xml.ElementList;
0061: import org.deegree.framework.xml.NamespaceContext;
0062: import org.deegree.framework.xml.XMLFragment;
0063: import org.deegree.framework.xml.XMLParsingException;
0064: import org.deegree.framework.xml.XMLTools;
0065: import org.deegree.i18n.Messages;
0066: import org.deegree.model.crs.CRSFactory;
0067: import org.deegree.model.crs.CoordinateSystem;
0068: import org.deegree.model.crs.UnknownCRSException;
0069: import org.deegree.ogcbase.CommonNamespaces;
0070: import org.deegree.ogcbase.InvalidGMLException;
0071: import org.w3c.dom.Document;
0072: import org.w3c.dom.Element;
0073: import org.w3c.dom.Node;
0074:
0075: /**
0076: * Adapter class for converting GML geometries to deegree geometries and vice versa. Some logical problems results from
0077: * the fact that an envelope isn't a geometry according to ISO 19107 (where the deegree geometry model is based on) but
0078: * according to GML2/3 specification it is.<br>
0079: * So if the wrap(..) method is called with an envelope a <tt>Surface</tt> will be returned representing the envelops
0080: * shape. To export an <tt>Envelope</tt> to a GML box/envelope two specialized export methods are available.<BR>
0081: * The export method(s) doesn't return a DOM element as one may expect but a <tt>StringBuffer</tt>. This is done
0082: * because the transformation from deegree geometries to GML mainly is required when a GML representation of a geometry
0083: * shall be serialized to a file or to a network connection. For both cases the string representation is required and it
0084: * is simply faster to create the string directly instead of first creating a DOM tree that after this must be
0085: * serialized to a string.<BR>
0086: * In future version geometries will be serialized to a stream.
0087: *
0088: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
0089: * @author last edited by: $Author: rbezema $
0090: *
0091: * @version $Revision: 10287 $, $Date: 2008-02-25 09:00:04 -0800 (Mon, 25 Feb 2008) $
0092: */
0093: public class GMLGeometryAdapter {
0094:
0095: private static final ILogger LOG = LoggerFactory
0096: .getLogger(GMLGeometryAdapter.class);
0097:
0098: private static final NamespaceContext nsContext = CommonNamespaces
0099: .getNamespaceContext();
0100:
0101: private static Map<String, CoordinateSystem> crsMap = new HashMap<String, CoordinateSystem>();
0102:
0103: private static final String COORD = CommonNamespaces.GML_PREFIX
0104: + ":coord";
0105:
0106: private static final String COORDINATES = CommonNamespaces.GML_PREFIX
0107: + ":coordinates";
0108:
0109: private static final String POS = CommonNamespaces.GML_PREFIX
0110: + ":pos";
0111:
0112: private static final String POSLIST = CommonNamespaces.GML_PREFIX
0113: + ":posList";
0114:
0115: /**
0116: * Returns true if the given localName != <code>null</code> or empty and matches one of the following:
0117: * <ul>
0118: * <li>Point</li>
0119: * <li>Center</li>
0120: * <li>LineString</li>
0121: * <li>Polygon</li>
0122: * <li>MultiPoint</li>
0123: * <li>MultiLineString</li>
0124: * <li>MultiPolygon</li>
0125: * <li>Box</li>
0126: * <li>Envelope</li>
0127: * <li>Curve</li>
0128: * <li>Surface</li>
0129: * <li>MultiCurve</li>
0130: * <li>MultiSurface</li>
0131: * <li>CompositeSurface</li>
0132: * </ul>
0133: *
0134: * @param localName
0135: * to check.
0136: * @return true if localName equal-ignore-case's one of the above strings.
0137: */
0138: public static boolean isGeometrieSupported(String localName) {
0139: if (localName == null || "".equals(localName.trim())) {
0140: return false;
0141: }
0142: return "Point".equalsIgnoreCase(localName)
0143: || "Center".equalsIgnoreCase(localName)
0144: || "LineString".equalsIgnoreCase(localName)
0145: || "Polygon".equalsIgnoreCase(localName)
0146: || "MultiPoint".equalsIgnoreCase(localName)
0147: || "MultiLineString".equalsIgnoreCase(localName)
0148: || "MultiPolygon".equalsIgnoreCase(localName)
0149: || "Box".equalsIgnoreCase(localName)
0150: || "Envelope".equalsIgnoreCase(localName)
0151: || "Curve".equalsIgnoreCase(localName)
0152: || "Surface".equalsIgnoreCase(localName)
0153: || "MultiCurve".equalsIgnoreCase(localName)
0154: || "MultiSurface".equalsIgnoreCase(localName)
0155: || "CompositeSurface".equalsIgnoreCase(localName);
0156: }
0157:
0158: /**
0159: * Converts the given string representation of a GML geometry object to a corresponding <code>Geometry</code>.
0160: * Notice that GML Boxes will be converted to Surfaces because in ISO 19107 Envelopes are no geometries.
0161: *
0162: * @param gml
0163: * @param srsName
0164: * default SRS for the geometry (may be overwritten in geometry elements)
0165: * @return corresponding geometry object
0166: * @throws GeometryException
0167: * @throws XMLParsingException
0168: */
0169: public static Geometry wrap(String gml, String srsName)
0170: throws GeometryException, XMLParsingException {
0171: StringReader sr = new StringReader(gml);
0172: Document doc = null;
0173: try {
0174: doc = XMLTools.parse(sr);
0175: } catch (Exception e) {
0176: LOG
0177: .logError("could not parse: '" + gml
0178: + "' as GML/XML", e);
0179: throw new XMLParsingException("could not parse: '" + gml
0180: + "' as GML/XML: " + e.getMessage());
0181: }
0182: return wrap(doc.getDocumentElement(), srsName);
0183: }
0184:
0185: /**
0186: * Converts the given DOM representation of a GML geometry to a corresponding <code>Geometry</code>. Notice that
0187: * GML Boxes will be converted to Surfaces because in ISO 19107 Envelopes are no geometries.
0188: * <p>
0189: * Currently, the following conversions are supported:
0190: * <ul>
0191: * <li>GML Point -> Point
0192: * <li>GML MultiPoint -> MultiPoint
0193: * <li>GML LineString -> Curve
0194: * <li>GML MultiLineString -> MultiCurve
0195: * <li>GML Polygon -> Surface
0196: * <li>GML MultiPolygon -> MultiSurface
0197: * <li>GML Box -> Surface
0198: * <li>GML Curve -> Curve
0199: * <li>GML Surface -> Surface
0200: * <li>GML MultiCurve -> MultiCurve
0201: * <li>GML MultiSurface -> MultiSurface
0202: * </ul>
0203: * <p>
0204: *
0205: * @param element
0206: * @param srsName
0207: * default SRS for the geometry
0208: * @return corresponding <code>Geometry</code> instance
0209: * @throws GeometryException
0210: * if type unsupported or conversion failed
0211: */
0212: public static Geometry wrap(Element element, String srsName)
0213: throws GeometryException {
0214:
0215: Geometry geometry = null;
0216: try {
0217: String name = element.getLocalName();
0218: if ((name.equals("Point")) || (name.equals("Center"))) {
0219: geometry = wrapPoint(element, srsName);
0220: } else if (name.equals("LineString")) {
0221: geometry = wrapLineString(element, srsName);
0222: } else if (name.equals("Polygon")) {
0223: geometry = wrapPolygon(element, srsName);
0224: } else if (name.equals("MultiPoint")) {
0225: geometry = wrapMultiPoint(element, srsName);
0226: } else if (name.equals("MultiLineString")) {
0227: geometry = wrapMultiLineString(element, srsName);
0228: } else if (name.equals("MultiPolygon")) {
0229: geometry = wrapMultiPolygon(element, srsName);
0230: } else if (name.equals("Box") || name.equals("Envelope")) {
0231: geometry = wrapBoxAsSurface(element, srsName);
0232: } else if (name.equals("Curve")) {
0233: geometry = wrapCurveAsCurve(element, srsName);
0234: } else if (name.equals("Surface")) {
0235: geometry = wrapSurfaceAsSurface(element, srsName);
0236: } else if (name.equals("MultiCurve")) {
0237: geometry = wrapMultiCurveAsMultiCurve(element, srsName);
0238: } else if (name.equals("MultiSurface")) {
0239: geometry = wrapMultiSurfaceAsMultiSurface(element,
0240: srsName);
0241: } else if (name.equals("CompositeSurface")) {
0242: geometry = wrapCompositeSurface(element, srsName);
0243: } else {
0244: new GeometryException("Not a supported geometry type: "
0245: + name);
0246: }
0247: } catch (Exception e) {
0248: LOG.logError(e.getMessage(), e);
0249: throw new GeometryException(StringTools
0250: .stackTraceToString(e));
0251: }
0252: return geometry;
0253: }
0254:
0255: /**
0256: * Returns an instance of {@link Envelope} created from the passed <code>gml:Box</code> or
0257: * <code>gml:Envelope</code> element.
0258: *
0259: * @param element
0260: * <code>gml:Box</code> or <code>gml:Envelope</code> element
0261: * @param srsName
0262: * default SRS for the geometry
0263: * @return instance of <code>Envelope</code>
0264: * @throws XMLParsingException
0265: * @throws InvalidGMLException
0266: * @throws UnknownCRSException
0267: */
0268: public static Envelope wrapBox(Element element, String srsName)
0269: throws XMLParsingException, InvalidGMLException,
0270: UnknownCRSException {
0271: srsName = findSrsName(element, srsName);
0272: CoordinateSystem crs = null;
0273: if (srsName != null) {
0274: crs = getCRS(srsName);
0275: }
0276: Position[] bb = null;
0277: List nl = XMLTools.getNodes(element, COORD, nsContext);
0278: if (nl != null && nl.size() > 0) {
0279: bb = new Position[2];
0280: bb[0] = createPositionFromCoord((Element) nl.get(0));
0281: bb[1] = createPositionFromCoord((Element) nl.get(1));
0282: } else {
0283: nl = XMLTools.getNodes(element, COORDINATES, nsContext);
0284: if (nl != null && nl.size() > 0) {
0285: bb = createPositionFromCoordinates((Element) nl.get(0));
0286: } else {
0287: nl = XMLTools.getNodes(element, POS, nsContext);
0288: if (nl != null && nl.size() > 0) {
0289: bb = new Position[2];
0290: bb[0] = createPositionFromPos((Element) nl.get(0));
0291: bb[1] = createPositionFromPos((Element) nl.get(1));
0292: } else {
0293: Element lowerCorner = (Element) XMLTools
0294: .getRequiredNode(element,
0295: "gml:lowerCorner", nsContext);
0296: Element upperCorner = (Element) XMLTools
0297: .getRequiredNode(element,
0298: "gml:upperCorner", nsContext);
0299: bb = new Position[2];
0300: bb[0] = createPositionFromCorner(lowerCorner);
0301: bb[1] = createPositionFromCorner(upperCorner);
0302: }
0303: }
0304: }
0305: Envelope box = GeometryFactory
0306: .createEnvelope(bb[0], bb[1], crs);
0307: return box;
0308: }
0309:
0310: /**
0311: * Returns an instance of {@link Curve} created from the passed <code>gml:Curve</code> element.
0312: *
0313: * @param element
0314: * <code>gml:Curve</code> element
0315: * @param srsName
0316: * default SRS for the geometry
0317: * @return corresponding Curve instance
0318: * @throws XMLParsingException
0319: * @throws GeometryException
0320: * @throws UnknownCRSException
0321: */
0322: protected static Curve wrapCurveAsCurve(Element element,
0323: String srsName) throws XMLParsingException,
0324: GeometryException, UnknownCRSException {
0325:
0326: srsName = findSrsName(element, srsName);
0327: CoordinateSystem crs = null;
0328: if (srsName != null) {
0329: crs = getCRS(srsName);
0330: }
0331:
0332: Element segment = (Element) XMLTools.getRequiredNode(element,
0333: "gml:segments", nsContext);
0334: CurveSegment[] segments = parseCurveSegments(crs, segment);
0335:
0336: return GeometryFactory.createCurve(segments, crs);
0337: }
0338:
0339: /**
0340: * parses CurveSegments
0341: *
0342: * @param crs
0343: * @param segment
0344: * @return CurveSegments
0345: * @throws XMLParsingException
0346: * @throws GeometryException
0347: */
0348: private static CurveSegment[] parseCurveSegments(
0349: CoordinateSystem crs, Element segment)
0350: throws XMLParsingException, GeometryException {
0351: List<Node> list = XMLTools.getNodes(segment, "child::*",
0352: nsContext);
0353:
0354: CurveSegment[] segments = new CurveSegment[list.size()];
0355: for (int i = 0; i < list.size(); i++) {
0356: if (list.get(i).getLocalName().equals("LineStringSegment")) {
0357: segments[i] = parseLineStringSegment((Element) list
0358: .get(i), crs);
0359: } else if (list.get(i).getLocalName().equals("Arc")) {
0360: segments[i] = parseArc((Element) list.get(i), crs);
0361: } else {
0362: throw new GeometryException(
0363: "not supported type for a CurveSegment: "
0364: + list.get(i).getLocalName());
0365: }
0366: }
0367: return segments;
0368: }
0369:
0370: /**
0371: * parses an Arc
0372: *
0373: * @param element
0374: * @param crs
0375: * @return
0376: * @throws GeometryException
0377: */
0378: private static CurveSegment parseArc(Element element,
0379: CoordinateSystem crs) throws GeometryException {
0380: CurveSegment segment = null;
0381: try {
0382: Position[] pos = createPositions(element, null);
0383: segment = GeometryFactory.createCurveSegment(pos, crs);
0384: } catch (Exception e) {
0385: throw new GeometryException(
0386: "Error creating segments for the element Arc.");
0387: }
0388: return segment;
0389: }
0390:
0391: /**
0392: * parses a LineStringSegment (linear interpolated CurveSegment)
0393: *
0394: * @param element
0395: * @param crs
0396: * @return
0397: * @throws GeometryException
0398: */
0399: private static CurveSegment parseLineStringSegment(Element element,
0400: CoordinateSystem crs) throws GeometryException {
0401: CurveSegment segment = null;
0402: try {
0403: Position[] pos = createPositions(element, null);
0404: segment = GeometryFactory.createCurveSegment(pos, crs);
0405: } catch (Exception e) {
0406: throw new GeometryException(
0407: "Error creating segments for the element LineStringSegment.");
0408: }
0409: return segment;
0410:
0411: }
0412:
0413: /**
0414: * Returns an instance of {@link MultiCurve} created from the passed <code>gml:MultiCurve</code> element.
0415: *
0416: * @param element
0417: * <code>gml:MultiCurve</code> element
0418: * @param srsName
0419: * default SRS for the geometry
0420: * @return <code>MultiCurve</code> instance
0421: * @throws XMLParsingException
0422: * @throws GeometryException
0423: * @throws UnknownCRSException
0424: * @throws InvalidGMLException
0425: */
0426: protected static MultiCurve wrapMultiCurveAsMultiCurve(
0427: Element element, String srsName)
0428: throws XMLParsingException, GeometryException,
0429: UnknownCRSException, InvalidGMLException {
0430:
0431: srsName = findSrsName(element, srsName);
0432: CoordinateSystem crs = null;
0433: if (srsName != null) {
0434: crs = getCRS(srsName);
0435: }
0436:
0437: MultiCurve multiCurve = null;
0438: try {
0439: // gml:curveMember
0440: List listCurveMember = XMLTools.getNodes(element,
0441: "gml:curveMember", nsContext);
0442: List<Curve> curveList = new ArrayList<Curve>();
0443: if (listCurveMember.size() > 0) {
0444:
0445: for (int i = 0; i < listCurveMember.size(); i++) {
0446: Element curveMember = (Element) listCurveMember
0447: .get(i);
0448: Element curve = (Element) XMLTools.getNode(
0449: curveMember, "gml:Curve", nsContext);
0450: if (curve != null) {
0451: curveList.add(wrapCurveAsCurve(curve, srsName));
0452: } else {
0453: curve = (Element) XMLTools.getRequiredNode(
0454: curveMember, "gml:LineString",
0455: nsContext);
0456: curveList.add(wrapLineString(curve, srsName));
0457: }
0458: }
0459: }
0460: Element curveMembers = (Element) XMLTools.getNode(element,
0461: "gml:curveMembers", nsContext);
0462: if (curveMembers != null) {
0463: // gml:curveMembers
0464: List listCurves = XMLTools.getNodes(curveMembers,
0465: "gml:Curve", nsContext);
0466: if (listCurves != null) {
0467: for (int i = 0; i < listCurves.size(); i++) {
0468: Element curve = (Element) listCurves.get(i);
0469: curveList.add(wrapCurveAsCurve(curve, srsName));
0470: }
0471: }
0472: listCurves = XMLTools.getNodes(curveMembers,
0473: "gml:LineString", nsContext);
0474: if (listCurves != null) {
0475: for (int i = 0; i < listCurves.size(); i++) {
0476: Element curve = (Element) listCurves.get(i);
0477: curveList.add(wrapLineString(curve, srsName));
0478: }
0479: }
0480: }
0481: Curve[] curves = new Curve[curveList.size()];
0482: multiCurve = GeometryFactory.createMultiCurve(curveList
0483: .toArray(curves), crs);
0484: } catch (XMLParsingException e) {
0485: LOG.logError(e.getMessage(), e);
0486: throw new XMLParsingException(
0487: "Error parsing <gml:curveMember> elements. Please check the xml document.");
0488: } catch (GeometryException e) {
0489: LOG.logError(e.getMessage(), e);
0490: throw new GeometryException(
0491: "Error creating a curve from the curve element. Please check the GML specifications "
0492: + "for correct element declaration.");
0493: }
0494: return multiCurve;
0495: }
0496:
0497: /**
0498: * Returns an instance of {@link Surface} created from the passed <code>gml:Surface</code> element.
0499: *
0500: * @param element
0501: * @param srsName
0502: * default SRS for the geometry
0503: * @return Surface
0504: * @throws XMLParsingException
0505: * @throws GeometryException
0506: * @throws UnknownCRSException
0507: */
0508: protected static Surface wrapSurfaceAsSurface(Element element,
0509: String srsName) throws XMLParsingException,
0510: GeometryException, UnknownCRSException {
0511:
0512: srsName = findSrsName(element, srsName);
0513: CoordinateSystem crs = null;
0514: if (srsName != null) {
0515: crs = getCRS(srsName);
0516: }
0517:
0518: Element patches = extractPatches(element);
0519: List<Element> polygonList = XMLTools.getRequiredElements(
0520: patches, "gml:Polygon | gml:PolygonPatch", nsContext);
0521:
0522: SurfacePatch[] surfacePatches = new SurfacePatch[polygonList
0523: .size()];
0524:
0525: for (int i = 0; i < polygonList.size(); i++) {
0526: Curve exteriorRing = null;
0527: Element polygon = polygonList.get(i);
0528: try {
0529: Element exterior = (Element) XMLTools
0530: .getNode(polygon,
0531: "gml:exterior | gml:outerBounderyIs",
0532: nsContext);
0533: if (exterior != null) {
0534: exteriorRing = parseRing(crs, exterior);
0535: } else {
0536: String msg = Messages
0537: .getMessage("GEOM_SURFACE_NO_EXTERIOR_RING");
0538: throw new XMLParsingException(msg);
0539: }
0540:
0541: List<Element> interiorList = XMLTools.getElements(
0542: polygon, "gml:interior | gml:outerBounderyIs",
0543: nsContext);
0544: Curve[] interiorRings = null;
0545: if (interiorList != null && interiorList.size() > 0) {
0546:
0547: interiorRings = new Curve[interiorList.size()];
0548:
0549: for (int j = 0; j < interiorRings.length; j++) {
0550: Element interior = interiorList.get(j);
0551: interiorRings[j] = parseRing(crs, interior);
0552: }
0553: }
0554: surfacePatches[i] = GeometryFactory.createSurfacePatch(
0555: exteriorRing, interiorRings, crs);
0556: } catch (InvalidGMLException e) {
0557: LOG.logError(e.getMessage(), e);
0558: throw new XMLParsingException(
0559: "Error parsing the polygon element '"
0560: + polygon.getNodeName()
0561: + "' to create a surface geometry.");
0562: }
0563:
0564: }
0565: Surface surface = null;
0566: try {
0567: surface = GeometryFactory
0568: .createSurface(surfacePatches, crs);
0569: } catch (GeometryException e) {
0570: throw new GeometryException(
0571: "Error creating a surface from '"
0572: + surfacePatches.length + "' polygons.");
0573: }
0574: return surface;
0575: }
0576:
0577: private static String findSrsName(Element element, String srsName)
0578: throws XMLParsingException {
0579: Node elem = element;
0580: String tmp = null;
0581: while (tmp == null && elem != null) {
0582: tmp = XMLTools.getNodeAsString(elem, "@srsName", nsContext,
0583: null);
0584: elem = elem.getParentNode();
0585: }
0586: elem = element;
0587: if (tmp != null) {
0588: srsName = tmp;
0589: } else {
0590: tmp = XMLTools.getNodeAsString(elem, "//@srsName",
0591: nsContext, srsName);
0592: if (tmp != null) {
0593: srsName = tmp;
0594: }
0595: }
0596: return srsName;
0597: }
0598:
0599: /**
0600: * parses a ring; a ring may is a gml:LinearRing or a gml:Ring
0601: *
0602: * @param crs
0603: * @param parent
0604: * parent of a gml:LinearRing or gml:Ring
0605: * @return curves of a ring
0606: * @throws XMLParsingException
0607: * @throws InvalidGMLException
0608: * @throws GeometryException
0609: */
0610: private static Curve parseRing(CoordinateSystem crs, Element parent)
0611: throws XMLParsingException, InvalidGMLException,
0612: GeometryException {
0613: String srsName = null;
0614: if (crs != null) {
0615: srsName = crs.getName();
0616: }
0617: List<CurveSegment> curveMembers = null;
0618: Element ring = (Element) XMLTools.getNode(parent,
0619: "gml:LinearRing", nsContext);
0620: if (ring != null) {
0621: Position[] exteriorRing = createPositions(ring, srsName);
0622: curveMembers = new ArrayList<CurveSegment>();
0623: curveMembers.add(GeometryFactory.createCurveSegment(
0624: exteriorRing, crs));
0625: } else {
0626: List<Node> members = XMLTools.getRequiredNodes(parent,
0627: "gml:Ring/gml:curveMember/child::*", nsContext);
0628: curveMembers = new ArrayList<CurveSegment>(members.size());
0629: for (Node node : members) {
0630: Curve curve = (Curve) wrap((Element) node, srsName);
0631: CurveSegment[] tmp = curve.getCurveSegments();
0632: for (int i = 0; i < tmp.length; i++) {
0633: curveMembers.add(tmp[i]);
0634: }
0635: }
0636: }
0637: CurveSegment[] cs = curveMembers
0638: .toArray(new CurveSegment[curveMembers.size()]);
0639:
0640: return GeometryFactory.createCurve(cs);
0641: }
0642:
0643: /**
0644: * Returns an instance of {@link MultiSurface} created from the passed <code>gml:MultiSurface</code> element.
0645: *
0646: * @param element
0647: * <code>gml:MultiSurface</code> element
0648: * @param srsName
0649: * default SRS for the geometry
0650: * @return MultiSurface
0651: * @throws XMLParsingException
0652: * @throws GeometryException
0653: * @throws InvalidGMLException
0654: * @throws UnknownCRSException
0655: */
0656: protected static MultiSurface wrapMultiSurfaceAsMultiSurface(
0657: Element element, String srsName)
0658: throws XMLParsingException, GeometryException,
0659: InvalidGMLException, UnknownCRSException {
0660:
0661: srsName = findSrsName(element, srsName);
0662: CoordinateSystem crs = null;
0663: if (srsName != null) {
0664: crs = getCRS(srsName);
0665: }
0666: MultiSurface multiSurface = null;
0667: try {
0668: List<Surface> surfaceList = new ArrayList<Surface>();
0669: // gml:surfaceMember
0670: List listSurfaceMember = XMLTools.getNodes(element,
0671: "gml:surfaceMember", nsContext);
0672: if (listSurfaceMember != null) {
0673: for (int i = 0; i < listSurfaceMember.size(); i++) {
0674: Element surfaceMember = (Element) listSurfaceMember
0675: .get(i);
0676: Element surface = (Element) XMLTools.getNode(
0677: surfaceMember, "gml:Surface", nsContext);
0678: if (surface != null) {
0679: surfaceList.add(wrapSurfaceAsSurface(surface,
0680: srsName));
0681: } else {
0682: surface = (Element) XMLTools.getRequiredNode(
0683: surfaceMember, ".//gml:Polygon",
0684: nsContext);
0685: surfaceList.add(wrapPolygon(surface, srsName));
0686: }
0687: }
0688: }
0689:
0690: Element surfaceMembers = (Element) XMLTools.getNode(
0691: element, "gml:surfaceMembers", nsContext);
0692: if (surfaceMembers != null) {
0693: // gml:surfaceMembers
0694:
0695: List listSurfaces = XMLTools.getNodes(surfaceMembers,
0696: "gml:Surface", nsContext);
0697: if (listSurfaces != null) {
0698: for (int i = 0; i < listSurfaces.size(); i++) {
0699: Element surface = (Element) listSurfaces.get(i);
0700: surfaceList.add(wrapSurfaceAsSurface(surface,
0701: srsName));
0702: }
0703: }
0704:
0705: listSurfaces = XMLTools.getNodes(surfaceMembers,
0706: ".//gml:Polygon", nsContext);
0707: if (listSurfaces != null) {
0708: for (int i = 0; i < listSurfaces.size(); i++) {
0709: Element surface = (Element) listSurfaces.get(i);
0710: surfaceList.add(wrapPolygon(surface, srsName));
0711: }
0712: }
0713: }
0714: Surface[] surfaces = new Surface[surfaceList.size()];
0715: surfaces = surfaceList.toArray(surfaces);
0716: multiSurface = GeometryFactory.createMultiSurface(surfaces,
0717: crs);
0718: } catch (XMLParsingException e) {
0719: LOG.logError(e.getMessage(), e);
0720: String msg = Messages
0721: .getMessage("GEOM_MULTISURFACE_PARSING_ERROR");
0722: throw new XMLParsingException(msg);
0723: } catch (GeometryException e) {
0724: LOG.logError(e.getMessage(), e);
0725: String msg = Messages
0726: .getMessage("GEOM_MULTISURFACE_FORMAT_ERROR");
0727: throw new GeometryException(msg);
0728: }
0729: return multiSurface;
0730: }
0731:
0732: /**
0733: * Returns a {@link Point} instance created from the passed <code>gml:Point</code> element.
0734: *
0735: * @param element
0736: * <code>gml:Point</code> element
0737: * @param srsName
0738: * default SRS for the geometry
0739: * @return instance of Point
0740: * @throws XMLParsingException
0741: * @throws UnknownCRSException
0742: */
0743: private static Point wrapPoint(Element element, String srsName)
0744: throws XMLParsingException, InvalidGMLException,
0745: UnknownCRSException {
0746:
0747: srsName = findSrsName(element, srsName);
0748: CoordinateSystem crs = null;
0749: if (srsName != null) {
0750: crs = getCRS(srsName);
0751: }
0752:
0753: Position[] bb = null;
0754: List nl = XMLTools.getNodes(element, COORD, nsContext);
0755: if (nl != null && nl.size() > 0) {
0756: bb = new Position[1];
0757: bb[0] = createPositionFromCoord((Element) nl.get(0));
0758: } else {
0759: nl = XMLTools.getNodes(element, COORDINATES, nsContext);
0760: if (nl != null && nl.size() > 0) {
0761: bb = createPositionFromCoordinates((Element) nl.get(0));
0762: } else {
0763: nl = XMLTools.getNodes(element, POS, nsContext);
0764: bb = new Position[1];
0765: bb[0] = createPositionFromPos((Element) nl.get(0));
0766: }
0767: }
0768: Point point = GeometryFactory.createPoint(bb[0], crs);
0769: return point;
0770: }
0771:
0772: /**
0773: * Returns a {@link Curve} instance created from the passed <code>gml:LineString</code> element.
0774: *
0775: * @param element
0776: * <code>gml:LineString</code> element
0777: * @param srsName
0778: * default SRS for the geometry
0779: * @return instance of Curve
0780: * @throws XMLParsingException
0781: * @throws UnknownCRSException
0782: */
0783: private static Curve wrapLineString(Element element, String srsName)
0784: throws XMLParsingException, GeometryException,
0785: InvalidGMLException, UnknownCRSException {
0786:
0787: srsName = findSrsName(element, srsName);
0788: CoordinateSystem crs = null;
0789: if (srsName != null) {
0790: crs = getCRS(srsName);
0791: }
0792: Position[] pos = createPositions(element, srsName);
0793: Curve curve = GeometryFactory.createCurve(pos, crs);
0794: return curve;
0795: }
0796:
0797: /**
0798: * Returns a {@link Surface} instance created from the passed <code>gml:Polygon</code> element.
0799: *
0800: * @param element
0801: * <code>gml:Polygon</code> element
0802: * @param srsName
0803: * default SRS for the geometry
0804: * @return instance of Surface
0805: * @throws XMLParsingException
0806: * @throws UnknownCRSException
0807: */
0808: private static Surface wrapPolygon(Element element, String srsName)
0809: throws XMLParsingException, GeometryException,
0810: InvalidGMLException, UnknownCRSException {
0811:
0812: srsName = findSrsName(element, srsName);
0813: CoordinateSystem crs = null;
0814: if (srsName != null) {
0815: crs = getCRS(srsName);
0816: }
0817:
0818: List nl = XMLTools.getNodes(element,
0819: CommonNamespaces.GML_PREFIX + ":outerBoundaryIs",
0820: nsContext);
0821: if (nl == null || nl.size() == 0) {
0822: nl = XMLTools.getRequiredNodes(element,
0823: CommonNamespaces.GML_PREFIX + ":exterior",
0824: nsContext);
0825: }
0826: Element outs = (Element) nl.get(0);
0827: nl = XMLTools.getRequiredNodes(outs,
0828: CommonNamespaces.GML_PREFIX + ":LinearRing", nsContext);
0829: Element ring = (Element) nl.get(0);
0830: nl = XMLTools.getNodes(ring, COORDINATES, nsContext);
0831: Position[] outerRing = createPositions(ring, srsName);
0832:
0833: Position[][] innerRings = null;
0834: List inns = XMLTools.getNodes(element,
0835: CommonNamespaces.GML_PREFIX + ":innerBoundaryIs",
0836: nsContext);
0837: if (inns == null || inns.size() == 0) {
0838: inns = XMLTools.getNodes(element,
0839: CommonNamespaces.GML_PREFIX + ":interior",
0840: nsContext);
0841: }
0842: if (inns != null && inns.size() > 0) {
0843: innerRings = new Position[inns.size()][];
0844: for (int i = 0; i < innerRings.length; i++) {
0845:
0846: nl = XMLTools.getRequiredNodes((Node) inns.get(i),
0847: CommonNamespaces.GML_PREFIX + ":LinearRing",
0848: nsContext);
0849:
0850: ring = (Element) nl.get(0);
0851: innerRings[i] = createPositions(ring, srsName);
0852: }
0853: }
0854:
0855: SurfaceInterpolation si = new SurfaceInterpolationImpl();
0856: Surface surface = GeometryFactory.createSurface(outerRing,
0857: innerRings, si, crs);
0858: return surface;
0859: }
0860:
0861: /**
0862: * Returns a {@link MultiPoint} instance created from the passed <code>gml:MultiPoint</code> element.
0863: *
0864: * @param element
0865: * <code>gml:MultiPoint</code> element
0866: * @param srsName
0867: * default SRS for the geometry
0868: * @return instance of MultiPoint
0869: * @throws XMLParsingException
0870: * @throws UnknownCRSException
0871: */
0872: private static MultiPoint wrapMultiPoint(Element element,
0873: String srsName) throws XMLParsingException,
0874: InvalidGMLException, UnknownCRSException {
0875:
0876: srsName = findSrsName(element, srsName);
0877: CoordinateSystem crs = null;
0878: if (srsName != null) {
0879: crs = getCRS(srsName);
0880: }
0881:
0882: List<Point> pointList = new ArrayList<Point>();
0883: List listPointMember = XMLTools.getNodes(element,
0884: "gml:pointMember", nsContext);
0885: if (listPointMember != null) {
0886: for (int i = 0; i < listPointMember.size(); i++) {
0887: Element pointMember = (Element) listPointMember.get(i);
0888: Element point = (Element) XMLTools.getNode(pointMember,
0889: "gml:Point", nsContext);
0890: pointList.add(wrapPoint(point, srsName));
0891: }
0892: }
0893:
0894: Element pointMembers = (Element) XMLTools.getNode(element,
0895: "gml:pointMembers", nsContext);
0896: if (pointMembers != null) {
0897: List pointElems = XMLTools.getNodes(pointMembers,
0898: "gml:Point", nsContext);
0899: for (int j = 0; j < pointElems.size(); j++) {
0900: pointList.add(wrapPoint((Element) pointElems.get(j),
0901: srsName));
0902: }
0903: }
0904:
0905: Point[] points = new Point[pointList.size()];
0906: return GeometryFactory.createMultiPoint(pointList
0907: .toArray(points), crs);
0908:
0909: }
0910:
0911: /**
0912: * Returns a {@link MultiCurve} instance created from the passed <code>gml:MultiLineString</code> element.
0913: *
0914: * @param element
0915: * <code>gml:MultiLineString</code> element
0916: * @param srsName
0917: * default SRS for the geometry
0918: * @return instance of MultiCurve
0919: * @throws XMLParsingException
0920: * @throws UnknownCRSException
0921: */
0922: private static MultiCurve wrapMultiLineString(Element element,
0923: String srsName) throws XMLParsingException,
0924: GeometryException, InvalidGMLException, UnknownCRSException {
0925:
0926: srsName = findSrsName(element, srsName);
0927: CoordinateSystem crs = null;
0928: if (srsName != null) {
0929: crs = getCRS(srsName);
0930: }
0931:
0932: ElementList el = XMLTools.getChildElements("lineStringMember",
0933: CommonNamespaces.GMLNS, element);
0934: Curve[] curves = new Curve[el.getLength()];
0935: for (int i = 0; i < curves.length; i++) {
0936: curves[i] = wrapLineString(XMLTools.getFirstChildElement(el
0937: .item(i)), srsName);
0938: }
0939: MultiCurve mp = GeometryFactory.createMultiCurve(curves, crs);
0940: return mp;
0941: }
0942:
0943: /**
0944: * Returns a {@link MultiSurface} instance created from the passed <code>gml:MultiPolygon</code> element.
0945: *
0946: * @param element
0947: * <code>gml:MultiPolygon</code> element
0948: * @param srsName
0949: * default SRS for the geometry
0950: * @return instance of MultiCurve
0951: *
0952: * @throws XMLParsingException
0953: * @throws UnknownCRSException
0954: */
0955: private static MultiSurface wrapMultiPolygon(Element element,
0956: String srsName) throws XMLParsingException,
0957: GeometryException, InvalidGMLException, UnknownCRSException {
0958:
0959: srsName = findSrsName(element, srsName);
0960: CoordinateSystem crs = null;
0961: if (srsName != null) {
0962: crs = getCRS(srsName);
0963: }
0964:
0965: ElementList el = XMLTools.getChildElements("polygonMember",
0966: CommonNamespaces.GMLNS, element);
0967: Surface[] surfaces = new Surface[el.getLength()];
0968: for (int i = 0; i < surfaces.length; i++) {
0969: surfaces[i] = wrapPolygon(XMLTools.getFirstChildElement(el
0970: .item(i)), srsName);
0971: }
0972: return GeometryFactory.createMultiSurface(surfaces, crs);
0973: }
0974:
0975: /**
0976: * Returns a <code>Surface</code> created from the given <code>gml:Box</code> element. This method is useful
0977: * because an Envelope that would normally be created from a Box isn't a geometry in context of ISO 19107.
0978: *
0979: * @param element
0980: * <code>gml:Box</code> element
0981: * @return instance of <code>Surface</code>
0982: * @throws XMLParsingException
0983: * @throws UnknownCRSException
0984: */
0985: private static Surface wrapBoxAsSurface(Element element,
0986: String srsName) throws XMLParsingException,
0987: GeometryException, InvalidGMLException, UnknownCRSException {
0988: Envelope env = wrapBox(element, srsName);
0989: return GeometryFactory.createSurface(env, env
0990: .getCoordinateSystem());
0991: }
0992:
0993: /**
0994: * Returns an instance of {@link CompositeSurface} created from the passed <code>gml:CompositeSurface</code>
0995: * element.
0996: *
0997: * TODO
0998: *
0999: * @param element
1000: * @param srsName
1001: * default SRS for the geometry
1002: * @return CompositeSurface
1003: * @throws GeometryException
1004: */
1005: private static CompositeSurface wrapCompositeSurface(
1006: Element element, String srsName) {
1007: throw new UnsupportedOperationException(
1008: "#wrapCompositeSurface(Element) is not implemented as yet. Work in Progress.");
1009: }
1010:
1011: /**
1012: * Extract the <gml:patches> node from a <gml:Surface> element.
1013: *
1014: * @param surface
1015: * @return Element
1016: * @throws XMLParsingException
1017: */
1018: private static Element extractPatches(Element surface)
1019: throws XMLParsingException {
1020: Element patches = null;
1021: try {
1022: patches = (Element) XMLTools.getRequiredNode(surface,
1023: "gml:patches", nsContext);
1024: } catch (XMLParsingException e) {
1025: throw new XMLParsingException(
1026: "Error retrieving the patches element from the surface element.");
1027: }
1028: return patches;
1029: }
1030:
1031: /**
1032: * returns an instance of CS_CoordinateSystem corrsponding to the passed crs name
1033: *
1034: * @param name
1035: * name of the crs
1036: *
1037: * @return CS_CoordinateSystem
1038: * @throws UnknownCRSException
1039: */
1040: private static CoordinateSystem getCRS(String name)
1041: throws UnknownCRSException {
1042:
1043: if ((name != null) && (name.length() > 2)) {
1044: if (name.startsWith("http://www.opengis.net/gml/srs/")) {
1045: // as declared in the GML 2.1.1 specification
1046: // http://www.opengis.net/gml/srs/epsg.xml#4326
1047: int p = name.lastIndexOf("/");
1048:
1049: if (p >= 0) {
1050: name = name.substring(p, name.length());
1051: p = name.indexOf(".");
1052:
1053: String s1 = name.substring(1, p).toUpperCase();
1054: p = name.indexOf("#");
1055:
1056: String s2 = name.substring(p + 1, name.length());
1057: name = s1 + ":" + s2;
1058: }
1059: }
1060: }
1061:
1062: CoordinateSystem crs = crsMap.get(name);
1063: if (crs == null) {
1064: crs = CRSFactory.create(name);
1065: crsMap.put(name, crs);
1066: }
1067: return crs;
1068: }
1069:
1070: private static Position createPositionFromCorner(Element corner)
1071: throws InvalidGMLException {
1072:
1073: String tmp = XMLTools.getAttrValue(corner, null, "dimension",
1074: null);
1075: int dim = 0;
1076: if (tmp != null) {
1077: dim = Integer.parseInt(tmp);
1078: }
1079: tmp = XMLTools.getStringValue(corner);
1080: double[] vals = StringTools.toArrayDouble(tmp, ", ");
1081: if (dim != 0) {
1082: if (vals.length != dim) {
1083: throw new InvalidGMLException(
1084: "dimension must be equal to the number of coordinate values defined "
1085: + "in pos element.");
1086: }
1087: } else {
1088: dim = vals.length;
1089: }
1090:
1091: Position pos = null;
1092: if (dim == 3) {
1093: pos = GeometryFactory.createPosition(vals[0], vals[1],
1094: vals[2]);
1095: } else {
1096: pos = GeometryFactory.createPosition(vals[0], vals[1]);
1097: }
1098:
1099: return pos;
1100:
1101: }
1102:
1103: /**
1104: * returns an instance of Position created from the passed coord
1105: *
1106: * @param element
1107: * <coord>
1108: *
1109: * @return instance of <tt>Position</tt>
1110: *
1111: * @throws XMLParsingException
1112: */
1113: private static Position createPositionFromCoord(Element element)
1114: throws XMLParsingException {
1115:
1116: Position pos = null;
1117: Element elem = XMLTools.getRequiredChildElement("X",
1118: CommonNamespaces.GMLNS, element);
1119: double x = Double.parseDouble(XMLTools.getStringValue(elem));
1120: elem = XMLTools.getRequiredChildElement("Y",
1121: CommonNamespaces.GMLNS, element);
1122: double y = Double.parseDouble(XMLTools.getStringValue(elem));
1123: elem = XMLTools.getChildElement("Z", CommonNamespaces.GMLNS,
1124: element);
1125:
1126: if (elem != null) {
1127: double z = Double
1128: .parseDouble(XMLTools.getStringValue(elem));
1129: pos = GeometryFactory
1130: .createPosition(new double[] { x, y, z });
1131: } else {
1132: pos = GeometryFactory.createPosition(new double[] { x, y });
1133: }
1134:
1135: return pos;
1136: }
1137:
1138: /**
1139: * returns an array of Positions created from the passed coordinates
1140: *
1141: * @param element
1142: * <coordinates>
1143: *
1144: * @return instance of <tt>Position[]</tt>
1145: *
1146: * @throws XMLParsingException
1147: */
1148: private static Position[] createPositionFromCoordinates(
1149: Element element) {
1150:
1151: Position[] points = null;
1152: // fixing the failure coming from the usage of the xmltools.getAttrib method
1153: String ts = XMLTools.getAttrValue(element, null, "ts", " ");
1154:
1155: // not used because javas current decimal seperator will be used
1156: // String ds = XMLTools.getAttrValue( element, null, "decimal", "." );
1157: String cs = XMLTools.getAttrValue(element, null, "cs", ",");
1158:
1159: String value = XMLTools.getStringValue(element).trim();
1160:
1161: // first tokenizer, tokens the tuples
1162: StringTokenizer tuple = new StringTokenizer(value, ts);
1163: points = new Position[tuple.countTokens()];
1164: int i = 0;
1165: while (tuple.hasMoreTokens()) {
1166: String s = tuple.nextToken();
1167: // second tokenizer, tokens the coordinates
1168: StringTokenizer coort = new StringTokenizer(s, cs);
1169: double[] p = new double[coort.countTokens()];
1170:
1171: for (int k = 0; k < p.length; k++) {
1172: s = coort.nextToken();
1173: p[k] = Double.parseDouble(s);
1174: }
1175:
1176: points[i++] = GeometryFactory.createPosition(p);
1177: }
1178:
1179: return points;
1180: }
1181:
1182: /**
1183: * creates a <tt>Point</tt> from the passed <pos> element containing a GML pos.
1184: *
1185: * @param element
1186: * @return created <tt>Point</tt>
1187: * @throws XMLParsingException
1188: * @throws InvalidGMLException
1189: */
1190: private static Position createPositionFromPos(Element element)
1191: throws InvalidGMLException {
1192:
1193: String tmp = XMLTools.getAttrValue(element, null, "dimension",
1194: null);
1195: int dim = 0;
1196: if (tmp != null) {
1197: dim = Integer.parseInt(tmp);
1198: } else {
1199: tmp = element.getAttribute("srsDimension");
1200: if (tmp != null && !"".equals(tmp.trim())) {
1201: dim = Integer.parseInt(tmp);
1202: }
1203: }
1204: tmp = XMLTools.getStringValue(element);
1205: double[] vals = StringTools.toArrayDouble(tmp, "\t\n\r\f ,");
1206: if (vals != null) {
1207: if (dim != 0) {
1208: if (vals.length != dim) {
1209: throw new InvalidGMLException(
1210: "The dimension of a position must be equal to the number of coordinate values defined in the pos element.");
1211: }
1212: } else {
1213: dim = vals.length;
1214: }
1215: } else {
1216: throw new InvalidGMLException(
1217: "The given element {"
1218: + element.getNamespaceURI()
1219: + "}"
1220: + element.getLocalName()
1221: + " does not contain any coordinates, this may not be!");
1222: }
1223:
1224: Position pos = null;
1225: if (dim == 3) {
1226: pos = GeometryFactory.createPosition(vals[0], vals[1],
1227: vals[2]);
1228: } else {
1229: pos = GeometryFactory.createPosition(vals[0], vals[1]);
1230: }
1231:
1232: return pos;
1233: }
1234:
1235: /**
1236: *
1237: * @param element
1238: * @return Position
1239: * @throws InvalidGMLException
1240: * @throws XMLParsingException
1241: */
1242: private static Position[] createPositionFromPosList(
1243: Element element, String srsName)
1244: throws InvalidGMLException, XMLParsingException {
1245:
1246: Node elem = element;
1247: while (srsName == null && elem != null) {
1248: srsName = XMLTools.getNodeAsString(elem, "@srsName",
1249: nsContext, srsName);
1250: elem = elem.getParentNode();
1251: }
1252:
1253: String srsDimension = XMLTools.getAttrValue(element, null,
1254: "srsDimension", null);
1255: if (LOG.getLevel() == ILogger.LOG_DEBUG) {
1256: XMLFragment doc = new XMLFragment(element);
1257: System.out.println(doc.getAsPrettyString());
1258: }
1259: int dim = 0;
1260: if (srsDimension != null) {
1261: dim = Integer.parseInt(srsDimension);
1262: }
1263: if (dim == 0) {
1264: // TODO
1265: // determine dimension from CRS
1266: // default dimension set.
1267: dim = 2;
1268:
1269: }
1270:
1271: String axisLabels = XMLTools.getAttrValue(element, null,
1272: "gml:axisAbbrev", null);
1273:
1274: String uomLabels = XMLTools.getAttrValue(element, null,
1275: "uomLabels", null);
1276:
1277: if (srsName == null) {
1278: if (srsDimension != null) {
1279: throw new InvalidGMLException(
1280: "Attribute srsDimension cannot be defined unless attribute srsName has been defined.");
1281: }
1282: if (axisLabels != null) {
1283: throw new InvalidGMLException(
1284: "Attribute axisLabels cannot be defined unless attribute srsName has been defined.");
1285: }
1286:
1287: }
1288: if (axisLabels == null) {
1289: if (uomLabels != null) {
1290: throw new InvalidGMLException(
1291: "Attribute uomLabels cannot be defined unless attribute axisLabels has been defined.");
1292: }
1293: }
1294: String tmp = XMLTools.getStringValue(element);
1295: double[] values = StringTools.toArrayDouble(tmp, "\t\n\r\f ,");
1296: int size = values.length / dim;
1297: LOG.logDebug("Number of points = ", size);
1298: LOG.logDebug("Size of the original array: ", values.length);
1299: LOG.logDebug("Dimension: ", dim);
1300:
1301: if (values.length < 4) {
1302: throw new InvalidGMLException(
1303: "A point list must have minimum 2 coordinate tuples. Here only '"
1304: + size + "' are defined.");
1305: }
1306: double positions[][] = new double[size][dim];
1307: int a = 0, b = 0;
1308: for (int i = 0; i < values.length; i++) {
1309: if (b == dim) {
1310: a++;
1311: b = 0;
1312: }
1313: positions[a][b] = values[i];
1314: b++;
1315: }
1316:
1317: Position[] position = new Position[positions.length];
1318: for (int i = 0; i < positions.length; i++) {
1319: double[] vals = positions[i];
1320: if (dim == 3) {
1321: position[i] = GeometryFactory.createPosition(vals[0],
1322: vals[1], vals[2]);
1323: } else {
1324: position[i] = GeometryFactory.createPosition(vals[0],
1325: vals[1]);
1326: }
1327: }
1328:
1329: return position;
1330:
1331: }
1332:
1333: /**
1334: * creates an array of <tt>Position</tt>s from the <coordinates> or <pos> Elements located as children under the
1335: * passed parent element.
1336: * <p>
1337: * example:<br>
1338: *
1339: * <pre>
1340: * <gml:Box>
1341: * <gml:coordinates cs="," decimal="." ts=" ">0,0 4000,4000</gml:coordinates>
1342: * </gml:Box>
1343: * </pre>
1344: *
1345: * </p>
1346: *
1347: * @param parent
1348: * @param srsName
1349: * @return
1350: * @throws XMLParsingException
1351: * @throws InvalidGMLException
1352: */
1353: private static Position[] createPositions(Element parent,
1354: String srsName) throws XMLParsingException,
1355: InvalidGMLException {
1356:
1357: List nl = XMLTools.getNodes(parent, COORDINATES, nsContext);
1358: Position[] pos = null;
1359: if (nl != null && nl.size() > 0) {
1360: pos = createPositionFromCoordinates((Element) nl.get(0));
1361: } else {
1362: nl = XMLTools.getNodes(parent, POS, nsContext);
1363: if (nl != null && nl.size() > 0) {
1364: pos = new Position[nl.size()];
1365: for (int i = 0; i < pos.length; i++) {
1366: pos[i] = createPositionFromPos((Element) nl.get(i));
1367: }
1368: } else {
1369: Element posList = (Element) XMLTools.getRequiredNode(
1370: parent, POSLIST, nsContext);
1371: if (posList != null) {
1372: pos = createPositionFromPosList(posList, srsName);
1373: }
1374: }
1375: }
1376: return pos;
1377: }
1378:
1379: /**
1380: * Creates a GML representation from the passed <code>Geometry<code>
1381: *
1382: * @param geometry
1383: * @param target
1384: * @throws GeometryException
1385: */
1386: public static PrintWriter export(Geometry geometry,
1387: OutputStream target) throws GeometryException {
1388:
1389: PrintWriter printwriter = new PrintWriter(target);
1390:
1391: if (geometry instanceof SurfacePatch) {
1392: geometry = new SurfaceImpl((SurfacePatch) geometry);
1393: } else if (geometry instanceof LineString) {
1394: geometry = new CurveImpl((LineString) geometry);
1395: }
1396: // create geometries from the wkb considering the geomerty typ
1397: if (geometry instanceof Point) {
1398: exportPoint((Point) geometry, printwriter);
1399: } else if (geometry instanceof Curve) {
1400: exportCurve((Curve) geometry, printwriter);
1401: } else if (geometry instanceof Surface) {
1402: exportSurface((Surface) geometry, printwriter);
1403: } else if (geometry instanceof MultiPoint) {
1404: exportMultiPoint((MultiPoint) geometry, printwriter);
1405: } else if (geometry instanceof MultiCurve) {
1406: exportMultiCurve((MultiCurve) geometry, printwriter);
1407: } else if (geometry instanceof MultiSurface) {
1408: exportMultiSurface((MultiSurface) geometry, printwriter);
1409: }
1410: printwriter.flush();
1411: return printwriter;
1412: }
1413:
1414: /**
1415: * Creates a GML representation from the passed <code>Geometry</code>.
1416: *
1417: * @param geometry
1418: * @return a string buffer containing the XML
1419: * @throws GeometryException
1420: */
1421: public static StringBuffer export(Geometry geometry)
1422: throws GeometryException {
1423:
1424: ByteArrayOutputStream bos = new ByteArrayOutputStream(5000);
1425:
1426: export(geometry, bos);
1427:
1428: return new StringBuffer(new String(bos.toByteArray()));
1429: }
1430:
1431: /**
1432: * creates a GML representation from the passed <tt>Envelope</tt>. This method is required because in ISO 19107
1433: * Envelops are no geometries.
1434: *
1435: * @param envelope
1436: * @return
1437: * @throws GeometryException
1438: */
1439: public static StringBuffer exportAsBox(Envelope envelope) {
1440:
1441: StringBuffer sb = new StringBuffer(
1442: "<gml:Box xmlns:gml='http://www.opengis.net/gml'>");
1443: sb.append("<gml:coordinates cs=\",\" decimal=\".\" ts=\" \">");
1444: sb.append(envelope.getMin().getX()).append(',');
1445: sb.append(envelope.getMin().getY());
1446: int dim = envelope.getMax().getCoordinateDimension();
1447: if (dim == 3) {
1448: sb.append(',').append(envelope.getMin().getZ());
1449: }
1450: sb.append(' ').append(envelope.getMax().getX());
1451: sb.append(',').append(envelope.getMax().getY());
1452: if (dim == 3) {
1453: sb.append(',').append(envelope.getMax().getZ());
1454: }
1455: sb.append("</gml:coordinates></gml:Box>");
1456:
1457: return sb;
1458: }
1459:
1460: /**
1461: * creates a GML representation from the passed <tt>Envelope</tt>. This method is required because in ISO 19107
1462: * Envelops are no geometries.
1463: *
1464: * @param envelope
1465: * @return
1466: * @throws GeometryException
1467: */
1468: public static StringBuffer exportAsEnvelope(Envelope envelope) {
1469:
1470: StringBuffer sb = new StringBuffer("<gml:Envelope ");
1471: sb.append("xmlns:gml='http://www.opengis.net/gml'>");
1472: sb.append("<gml:coordinates cs=\",\" decimal=\".\" ts=\" \">");
1473: sb.append(envelope.getMin().getX()).append(',');
1474: sb.append(envelope.getMin().getY());
1475: int dim = envelope.getMax().getCoordinateDimension();
1476: if (dim == 3) {
1477: sb.append(',').append(envelope.getMin().getZ());
1478: }
1479: sb.append(' ').append(envelope.getMax().getX());
1480: sb.append(',').append(envelope.getMax().getY());
1481: if (dim == 3) {
1482: sb.append(',').append(envelope.getMax().getZ());
1483: }
1484: sb.append("</gml:coordinates></gml:Envelope>");
1485:
1486: return sb;
1487: }
1488:
1489: /**
1490: * creates a GML expression of a point geometry
1491: *
1492: * @param point
1493: * point geometry
1494: *
1495: * @return
1496: */
1497: private static void exportPoint(Point point, PrintWriter pw) {
1498:
1499: String crs = null;
1500: int dim = point.getCoordinateDimension();
1501: if (point.getCoordinateSystem() != null) {
1502: crs = point.getCoordinateSystem().getIdentifier().replace(
1503: ' ', ':');
1504: dim = point.getCoordinateSystem().getDimension();
1505: }
1506: String srs = null;
1507: if (crs != null) {
1508: srs = "<gml:Point srsName=\"" + crs + "\">";
1509: } else {
1510: srs = "<gml:Point>";
1511: }
1512: pw.println(srs);
1513:
1514: if (dim != 0) {
1515: String dimension = "<gml:pos srsDimension=\"" + dim + "\">";
1516: pw.print(dimension);
1517: } else {
1518: pw.print("<gml:pos>");
1519: }
1520:
1521: String coordinates = point.getX() + " " + point.getY();
1522: if (dim == 3) {
1523: coordinates = coordinates + " " + point.getZ();
1524: }
1525: pw.print(coordinates);
1526: pw.println("</gml:pos>");
1527: pw.print("</gml:Point>");
1528:
1529: }
1530:
1531: /**
1532: * creates a GML expression of a curve geometry
1533: *
1534: * @param o
1535: * curve geometry
1536: *
1537: * @return
1538: *
1539: * @throws GeometryException
1540: */
1541: private static void exportCurve(Curve o, PrintWriter pw)
1542: throws GeometryException {
1543:
1544: String crs = null;
1545: if (o.getCoordinateSystem() != null) {
1546: crs = o.getCoordinateSystem().getName().replace(' ', ':');
1547: }
1548: String srs = null;
1549: if (crs != null) {
1550: srs = "<gml:Curve srsName=\"" + crs + "\">";
1551: } else {
1552: srs = "<gml:Curve>";
1553: }
1554: pw.println(srs);
1555: pw.println("<gml:segments>");
1556:
1557: int curveSegments = o.getNumberOfCurveSegments();
1558: for (int i = 0; i < curveSegments; i++) {
1559: pw.print("<gml:LineStringSegment>");
1560: CurveSegment segment = o.getCurveSegmentAt(i);
1561: Position[] p = segment.getAsLineString().getPositions();
1562: pw.print("<gml:posList>");
1563: for (int j = 0; j < (p.length - 1); j++) {
1564: pw.print(p[j].getX() + " " + p[j].getY());
1565: if (o.getCoordinateDimension() == 3) {
1566: pw.print(' ');
1567: pw.print(p[j].getZ());
1568: pw.print(' ');
1569: } else {
1570: pw.print(' ');
1571: }
1572: }
1573: pw.print(p[p.length - 1].getX() + " "
1574: + p[p.length - 1].getY());
1575: if (o.getCoordinateDimension() == 3) {
1576: pw.print(" " + p[p.length - 1].getZ());
1577: }
1578: pw.println("</gml:posList>");
1579: pw.println("</gml:LineStringSegment>");
1580: }
1581: pw.println("</gml:segments>");
1582: pw.print("</gml:Curve>");
1583:
1584: }
1585:
1586: /**
1587: * @param sur
1588: * @throws RemoteException
1589: * @throws GeometryException
1590: */
1591: private static void exportSurface(Surface surface, PrintWriter pw)
1592: throws GeometryException {
1593:
1594: String crs = null;
1595: if (surface.getCoordinateSystem() != null) {
1596: crs = surface.getCoordinateSystem().getName().replace(' ',
1597: ':');
1598: }
1599: String srs = null;
1600: if (crs != null) {
1601: srs = "<gml:Surface srsName='" + crs + "'>";
1602: } else {
1603: srs = "<gml:Surface>";
1604: }
1605: pw.println(srs);
1606: int patches = surface.getNumberOfSurfacePatches();
1607: pw.println("<gml:patches>");
1608: for (int i = 0; i < patches; i++) {
1609: pw.println("<gml:PolygonPatch>");
1610: SurfacePatch patch = surface.getSurfacePatchAt(i);
1611: printExteriorRing(surface, pw, patch);
1612: printInteriorRing(surface, pw, patch);
1613: pw.println("</gml:PolygonPatch>");
1614: }
1615: pw.println("</gml:patches>");
1616: pw.print("</gml:Surface>");
1617:
1618: }
1619:
1620: /**
1621: * @param surface
1622: * @param pw
1623: * @param patch
1624: */
1625: private static void printInteriorRing(Surface surface,
1626: PrintWriter pw, SurfacePatch patch) {
1627: // interior rings
1628: Position[][] ip = patch.getInteriorRings();
1629: if (ip != null) {
1630: for (int j = 0; j < ip.length; j++) {
1631: pw.println("<gml:interior>");
1632: pw.println("<gml:LinearRing>");
1633: if (surface.getCoordinateSystem() != null) {
1634: printPositions(pw, ip[j], surface
1635: .getCoordinateDimension());
1636: } else {
1637: printPositions(pw, ip[j], 0);
1638: }
1639: pw.println("</gml:LinearRing>");
1640: pw.println("</gml:interior>");
1641: }
1642: }
1643: }
1644:
1645: /**
1646: * @param surface
1647: * @param pw
1648: * @param patch
1649: */
1650: private static void printExteriorRing(Surface surface,
1651: PrintWriter pw, SurfacePatch patch) {
1652: // exterior ring
1653: pw.print("<gml:exterior>");
1654: pw.print("<gml:LinearRing>");
1655: if (surface.getCoordinateSystem() != null) {
1656: printPositions(pw, patch.getExteriorRing(), surface
1657: .getCoordinateDimension());
1658: } else {
1659: printPositions(pw, patch.getExteriorRing(), 0);
1660: }
1661: pw.print("</gml:LinearRing>");
1662: pw.print("</gml:exterior>");
1663: }
1664:
1665: /**
1666: * TODO using this method for exporting Surfaces will change to output, so it must be tested carefully
1667: *
1668: * @param pw
1669: * @param ring
1670: * @param coordinateDimension
1671: */
1672: private static void printRing(PrintWriter pw, Ring ring,
1673: int coordinateDimension) {
1674: pw
1675: .print("<gml:Ring><gml:curveMember><gml:Curve><gml:segments>");
1676: CurveSegment[] cs = ring.getCurveSegments();
1677: for (int i = 0; i < cs.length; i++) {
1678: printCurveSegment(pw, cs[i], coordinateDimension);
1679: }
1680: pw
1681: .print("</gml:segments></gml:Curve></gml:curveMember></gml:Ring>");
1682:
1683: }
1684:
1685: /**
1686: *
1687: * @param pw
1688: * @param segment
1689: * @param coordinateDimension
1690: */
1691: private static void printCurveSegment(PrintWriter pw,
1692: CurveSegment segment, int coordinateDimension) {
1693: pw.print("<gml:LineStringSegment>");
1694: printPositions(pw, segment.getPositions(), coordinateDimension);
1695: pw.print("</gml:LineStringSegment>");
1696: }
1697:
1698: /**
1699: *
1700: * @param pw
1701: * @param p
1702: * @param coordinateDimension
1703: */
1704: private static void printPositions(PrintWriter pw, Position[] p,
1705: int coordinateDimension) {
1706: StringBuilder posList = new StringBuilder("<gml:posList");
1707:
1708: if (coordinateDimension > 0) {
1709: posList.append(" srsDimension='").append(
1710: coordinateDimension).append("' ");
1711: }
1712: posList.append(">");
1713: // pw.print( "<gml:posList>" );
1714: pw.print(posList);
1715:
1716: for (int j = 0; j < (p.length - 1); j++) {
1717: pw.print(p[j].getX() + " " + p[j].getY());
1718: if (coordinateDimension == 3) {
1719: pw.print(" " + p[j].getZ() + " ");
1720: } else {
1721: pw.print(' ');
1722: }
1723: }
1724: pw.print(p[p.length - 1].getX() + " " + p[p.length - 1].getY());
1725: if (coordinateDimension == 3) {
1726: pw.print(" " + p[p.length - 1].getZ());
1727: }
1728: pw.print("</gml:posList>");
1729: }
1730:
1731: /**
1732: * @param mp
1733: * @return
1734: * @throws RemoteException
1735: */
1736: private static void exportMultiPoint(MultiPoint mp, PrintWriter pw) {
1737:
1738: String crs = null;
1739: if (mp.getCoordinateSystem() != null) {
1740: crs = mp.getCoordinateSystem().getName().replace(' ', ':');
1741: }
1742: String srs = null;
1743: if (crs != null) {
1744: srs = "<gml:MultiPoint srsName=\"" + crs + "\">";
1745: } else {
1746: srs = "<gml:MultiPoint>";
1747: }
1748: pw.println(srs);
1749: pw.println("<gml:pointMembers>");
1750: for (int i = 0; i < mp.getSize(); i++) {
1751:
1752: pw.println("<gml:Point>");
1753: pw.print("<gml:pos>");
1754: pw.print(mp.getPointAt(i).getX() + " "
1755: + mp.getPointAt(i).getY());
1756: if (mp.getPointAt(i).getCoordinateDimension() == 3) {
1757: pw.print(" " + mp.getPointAt(i).getZ());
1758: }
1759: pw.println("</gml:pos>");
1760: pw.println("</gml:Point>");
1761: }
1762: pw.println("</gml:pointMembers>");
1763: pw.print("</gml:MultiPoint>");
1764:
1765: }
1766:
1767: /**
1768: * @param multiCurve
1769: * @return
1770: * @throws RemoteException
1771: * @throws GeometryException
1772: */
1773: private static void exportMultiCurve(MultiCurve multiCurve,
1774: PrintWriter pw) throws GeometryException {
1775:
1776: String crs = null;
1777: if (multiCurve.getCoordinateSystem() != null) {
1778: crs = multiCurve.getCoordinateSystem().getName().replace(
1779: ' ', ':');
1780: }
1781: String srs = null;
1782: if (crs != null) {
1783: srs = "<gml:MultiCurve srsName=\"" + crs + "\">";
1784: } else {
1785: srs = "<gml:MultiCurve>";
1786: }
1787: pw.println(srs);
1788:
1789: Curve[] curves = multiCurve.getAllCurves();
1790: pw.println("<gml:curveMembers>");
1791: for (int i = 0; i < curves.length; i++) {
1792: Curve curve = curves[i];
1793: pw.println("<gml:Curve>");
1794: pw.println("<gml:segments>");
1795: pw.println("<gml:LineStringSegment>");
1796: int numberCurveSegments = curve.getNumberOfCurveSegments();
1797: for (int j = 0; j < numberCurveSegments; j++) {
1798: CurveSegment curveSegment = curve.getCurveSegmentAt(j);
1799: Position[] p = curveSegment.getAsLineString()
1800: .getPositions();
1801: pw.print("<gml:posList>");
1802: for (int k = 0; k < (p.length - 1); k++) {
1803: pw.print(p[k].getX() + " " + p[k].getY());
1804: if (curve.getCoordinateDimension() == 3) {
1805: pw.print(" " + p[k].getZ() + " ");
1806: } else {
1807: pw.print(" ");
1808: }
1809: }
1810: pw.print(p[p.length - 1].getX() + " "
1811: + p[p.length - 1].getY());
1812: if (curve.getCoordinateDimension() == 3) {
1813: pw.print(" " + p[p.length - 1].getZ());
1814: }
1815: pw.println("</gml:posList>");
1816: }
1817: pw.println("</gml:LineStringSegment>");
1818: pw.println("</gml:segments>");
1819: pw.println("</gml:Curve>");
1820: }
1821: pw.println("</gml:curveMembers>");
1822: pw.print("</gml:MultiCurve>");
1823:
1824: }
1825:
1826: /**
1827: * @param multiSurface
1828: * @return
1829: * @throws RemoteException
1830: * @throws GeometryException
1831: */
1832: private static void exportMultiSurface(MultiSurface multiSurface,
1833: PrintWriter pw) throws GeometryException {
1834:
1835: String crs = null;
1836: if (multiSurface.getCoordinateSystem() != null) {
1837: crs = multiSurface.getCoordinateSystem().getName().replace(
1838: ' ', ':');
1839: }
1840: String srs = null;
1841: if (crs != null) {
1842: srs = "<gml:MultiSurface srsName=\"" + crs + "\">";
1843: } else {
1844: srs = "<gml:MultiSurface>";
1845: }
1846: pw.println(srs);
1847:
1848: Surface[] surfaces = multiSurface.getAllSurfaces();
1849:
1850: pw.println("<gml:surfaceMembers>");
1851: for (int i = 0; i < surfaces.length; i++) {
1852: Surface surface = surfaces[i];
1853: exportSurface(surface, pw);
1854: }
1855: pw.println("</gml:surfaceMembers>");
1856: // substitution as requested in issue
1857: // http://wald.intevation.org/tracker/index.php?func=detail&aid=477&group_id=27&atid=212
1858: // can be removed if it was inserted correctly
1859: // pw.println( "<gml:surfaceMembers>" );
1860: // for ( int i = 0; i < surfaces.length; i++ ) {
1861: // Surface surface = surfaces[i];
1862: // pw.println( "<gml:Surface>" );
1863: // pw.println( "<gml:patches>" );
1864: // pw.println( "<gml:Polygon>" );
1865: // int numberSurfaces = surface.getNumberOfSurfacePatches();
1866: // for ( int j = 0; j < numberSurfaces; j++ ) {
1867: // SurfacePatch surfacePatch = surface.getSurfacePatchAt( j );
1868: // printExteriorRing( surface, pw, surfacePatch );
1869: // printInteriorRing( surface, pw, surfacePatch );
1870: // }
1871: // pw.println( "</gml:Polygon>" );
1872: // pw.println( "</gml:patches>" );
1873: // pw.println( "</gml:Surface>" );
1874: // }
1875: // pw.println( "</gml:surfaceMembers>" );
1876: pw.print("</gml:MultiSurface>");
1877:
1878: }
1879:
1880: /**
1881: * Converts the string representation of a GML geometry object to a corresponding <code>Geometry</code>. Notice
1882: * that GML Boxes will be converted to Surfaces because in ISO 19107 Envelopes are no geometries.
1883: *
1884: * @param gml
1885: * @return corresponding geometry object
1886: * @throws GeometryException
1887: * @throws XMLParsingException
1888: * @deprecated this method cannot provide default SRS information, please use {@link #wrap(String,String)} instead
1889: */
1890: @Deprecated
1891: public static Geometry wrap(String gml) throws GeometryException,
1892: XMLParsingException {
1893: return wrap(gml, null);
1894: }
1895:
1896: /**
1897: * Converts a GML geometry object to a corresponding <tt>Geometry</tt>. Notice that GML Boxes will be converted
1898: * to Surfaces because in ISO 19107 Envelops are no geometries.
1899: * <p>
1900: * Currently, the following conversions are supported:
1901: * <ul>
1902: * <li>GML Point -> Point
1903: * <li>GML MultiPoint -> MultiPoint
1904: * <li>GML LineString -> Curve
1905: * <li>GML MultiLineString -> MultiCurve
1906: * <li>GML Polygon -> Surface
1907: * <li>GML MultiPolygon -> MultiSurface
1908: * <li>GML Box -> Surface
1909: * <li>GML Curve -> Curve
1910: * <li>GML Surface -> Surface
1911: * <li>GML MultiCurve -> MultiCurve
1912: * <li>GML MultiSurface -> MultiSurface
1913: * </ul>
1914: * <p>
1915: *
1916: * @param gml
1917: * @return the corresponding <tt>Geometry</tt>
1918: * @throws GeometryException
1919: * if type unsupported or conversion failed
1920: * @deprecated this method cannot provide default SRS information, please use {@link #wrap(Element,String)} instead
1921: */
1922: @Deprecated
1923: public static Geometry wrap(Element gml) throws GeometryException {
1924: return wrap(gml, null);
1925: }
1926:
1927: /**
1928: * returns a Envelope created from Box element
1929: *
1930: * @param element
1931: * <boundedBy>
1932: *
1933: * @return instance of <tt>Envelope</tt>
1934: *
1935: * @throws XMLParsingException
1936: * @throws InvalidGMLException
1937: * @throws UnknownCRSException
1938: * @deprecated this method cannot provide default SRS information, please use {@link #wrapBox(Element,String)}
1939: * instead
1940: */
1941: @Deprecated
1942: public static Envelope wrapBox(Element element)
1943: throws XMLParsingException, InvalidGMLException,
1944: UnknownCRSException {
1945: return wrapBox(element, null);
1946: }
1947:
1948: }
|