All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geolatte.geom.codec.PostgisWktDecoder Maven / Gradle / Ivy

Go to download

This geoLatte-geom library offers a geometry model that conforms to the OGC Simple Features for SQL specification.

There is a newer version: 1.9.1
Show newest version
/*
 * This file is part of the GeoLatte project.
 *
 *     GeoLatte 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, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     GeoLatte 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.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with GeoLatte.  If not, see .
 *
 * Copyright (C) 2010 - 2011 and Ownership of code is shared by:
 * Qmino bvba - Romeinsestraat 18 - 3001 Heverlee  (http://www.qmino.com)
 * Geovise bvba - Generaal Eisenhowerlei 9 - 2140 Antwerpen (http://www.geovise.com)
 */

package org.geolatte.geom.codec;

import org.geolatte.geom.*;
import org.geolatte.geom.crs.CoordinateReferenceSystem;
import org.geolatte.geom.crs.CoordinateReferenceSystems;
import org.geolatte.geom.crs.CrsRegistry;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.geolatte.geom.Geometries.*;

/**
 * A decoder for the Postgis WKT/EWKT representations as used in Postgis (at least 1.0 to 1.5+).
 * 

*

This class is not thread-safe

* * @author Karel Maesen, Geovise BVBA, 2011 */ class PostgisWktDecoder extends AbstractWktDecoder> implements WktDecoder { private final static PostgisWktVariant WKT_GEOM_TOKENS = new PostgisWktVariant(); private final static Pattern SRID_RE = Pattern.compile("^SRID=(.*);", Pattern.CASE_INSENSITIVE); private String wktString; private CoordinateReferenceSystem crs; public PostgisWktDecoder() { super(WKT_GEOM_TOKENS); } protected PostgisWktDecoder(WktVariant wktVariant) { super(wktVariant); } public Geometry decode(String wkt) { return decode(wkt, (CoordinateReferenceSystem)null); } @Override @SuppressWarnings("unchecked") public

Geometry

decode(String wkt, CoordinateReferenceSystem

crs) { if (wkt == null || wkt.isEmpty()) { throw new WktDecodeException("Null or empty string cannot be decoded into a geometry"); } prepare(wkt, crs); initializeTokenizer(crs != null); return (Geometry

)decodeGeometry(this.crs); } /** * The instance fields wktString and crsId are initialized prior to decoding. For postgis EWKT that entails * extracting the SRID prefix (if any) from the WKT string. * * @param wkt the WKT representation */ private

void prepare(String wkt, CoordinateReferenceSystem

crs) { Matcher matcher = SRID_RE.matcher(wkt); if (matcher.find()) { int srid = Integer.parseInt(matcher.group(1)); this.crs = crs != null? crs : CrsRegistry.getCoordinateReferenceSystemForEPSG(srid, CoordinateReferenceSystems.PROJECTED_2D_METER); wktString = wkt.substring(matcher.end()); } else { this.crs = crs != null ? crs : CoordinateReferenceSystems.PROJECTED_2D_METER; wktString = wkt; } } private void initializeTokenizer(boolean forceToCRS) { setTokenizer(new WktTokenizer(wktString, getWktVariant(), crs, forceToCRS)); nextToken(); } private

Geometry

decodeGeometry(CoordinateReferenceSystem

crs) { if (!(currentToken instanceof WktGeometryToken)) { throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } GeometryType type = ((WktGeometryToken) currentToken).getType(); nextToken(); switch (type) { case POINT: return decodePointText(crs); case LINESTRING: return decodeLineStringText(crs); case POLYGON: return decodePolygonText(crs); case GEOMETRYCOLLECTION: return decodeGeometryCollection(crs); case MULTIPOINT: return decodeMultiPoint(crs); case MULTILINESTRING: return decodeMultiLineString(crs); case MULTIPOLYGON: return decodeMultiPolygon(crs); } throw new WktDecodeException("Unsupported geometry type in Wkt: " + type); } private

MultiPolygon

decodeMultiPolygon(CoordinateReferenceSystem

crs) { if (matchesOpenList()) { List> polygons = new ArrayList>(); while (!matchesCloseList()) { polygons.add(decodePolygonText(crs)); matchesElementSeparator(); } return mkMultiPolygon(polygons); } if (matchesEmptyToken()) { return new MultiPolygon

(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private

Geometry

decodeMultiLineString(CoordinateReferenceSystem

crs) { if (matchesOpenList()) { List> lineStrings = new ArrayList>(); while (!matchesCloseList()) { lineStrings.add(decodeLineStringText(crs)); matchesElementSeparator(); } return mkMultiLineString(lineStrings); } if (matchesEmptyToken()) { return new MultiLineString

(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private

Geometry

decodeMultiPoint(CoordinateReferenceSystem

crs) { if (matchesOpenList()) { List> points = new ArrayList>(); //this handles the case of the non-compliant MultiPoints in Postgis (e.g. // MULTIPOINT(10 10, 12 13) rather than MULTIPOINT((10 20), (30 40)) if (currentToken instanceof WktPointSequenceToken) { PositionSequence

positionSequence = ((WktPointSequenceToken

) currentToken).getPositions(); CoordinateReferenceSystem

tcrs = ((WktPointSequenceToken

) currentToken).getCoordinateReferenceSystem(); for (P p : positionSequence) { points.add(new Point

(p, tcrs)); } nextToken(); } while (!matchesCloseList()) { points.add(decodePointText(crs)); matchesElementSeparator(); } return mkMultiPoint(points); } if (matchesEmptyToken()) { return new MultiPoint

(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private

GeometryCollection> decodeGeometryCollection(CoordinateReferenceSystem

crs) { if (matchesOpenList()) { List> geometries = new ArrayList>(); while (!matchesCloseList()) { geometries.add(decodeGeometry(crs)); matchesElementSeparator(); } return mkGeometryCollection(geometries); } if (matchesEmptyToken()) { return new GeometryCollection>(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private

Polygon

decodePolygonText(CoordinateReferenceSystem

crs) { if (matchesOpenList()) { List> rings = new ArrayList>(); while (!matchesCloseList()) { LinearRing ring = decodeLinearRingText(crs); if (ring.isEmpty()) { throw new WktDecodeException("Empty ring found in polygon" + "Wkt: " + wktString); } rings.add(ring); matchesElementSeparator(); } return mkPolygon(rings); } if (matchesEmptyToken()) { return new Polygon

(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private

LinearRing

decodeLinearRingText(CoordinateReferenceSystem

crs) { try { WktPointSequenceToken

token = decodePointSequence(crs); if (token == null) throw new WktDecodeException("No Linear Ring when expected"); return new LinearRing

(token.getPositions(), token.getCoordinateReferenceSystem()); } catch (IllegalArgumentException ex) { throw new WktDecodeException(ex.getMessage()); } } private

LineString

decodeLineStringText(CoordinateReferenceSystem

crs) { WktPointSequenceToken

token = decodePointSequence(crs); if (token != null) { PositionSequence

positionSequence = token.getPositions(); CoordinateReferenceSystem

tcrs = token.getCoordinateReferenceSystem(); return new LineString

(positionSequence, tcrs); } if (matchesEmptyToken()) { return new LineString

(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private

Point

decodePointText(CoordinateReferenceSystem

crs) { WktPointSequenceToken

token = decodePointSequence(crs); if (token != null) { PositionSequence

positionSequence = token.getPositions(); CoordinateReferenceSystem

tcrs = token.getCoordinateReferenceSystem(); return new Point

(positionSequence, tcrs); } if (matchesEmptyToken()) { return new Point

(crs); } throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } private boolean matchesEmptyToken() { if (currentToken == WKT_GEOM_TOKENS.getEmpty()) { nextToken(); return true; } return false; } private

WktPointSequenceToken

decodePointSequence(CoordinateReferenceSystem

forceCrs) { WktPointSequenceToken

token = null; if (matchesOpenList()) { if (currentToken instanceof WktPointSequenceToken) { token = (WktPointSequenceToken

) currentToken; nextToken(); } else { throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } if (!matchesCloseList()) { throw new WktDecodeException(buildWrongSymbolAtPositionMsg()); } } return token; } private String buildWrongSymbolAtPositionMsg() { return "Wrong symbol at position: " + getTokenizerPosition() + " in Wkt: " + wktString; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy