/*
LWKT - A light WKT parser written in Java
Copyright (C) 2011 Francesco Cutruzzula' (www.cutruzzula.it)
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; either
version 2.1 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package it.cutruzzula.lwkt;
import it.cutruzzula.lwkt.geometry.AbstractGeometry;
import it.cutruzzula.lwkt.geometry.LineString;
import it.cutruzzula.lwkt.geometry.MultiLineString;
import it.cutruzzula.lwkt.geometry.MultiPoint;
import it.cutruzzula.lwkt.geometry.MultiPolygon;
import it.cutruzzula.lwkt.geometry.Point;
import it.cutruzzula.lwkt.geometry.Polygon;
import it.cutruzzula.lwkt.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/** The core class of the LWKT parser */
public class WKTParser {
private WKTParser() {}
/** Method to parse a WKT string to get GML 2 output.<br/><br/>
* @param input The WKT string
* @return The GML v2 content
* @throws Exception A generic exception thrown in parsing
*/
public static String parseToGML2(String input) throws Exception {
return GMLWriter.getGML(parse(input), 2, null);
}
/** Method to parse a WKT string to get GML 2 output.<br/><br/>
* @param input The WKT string
* @param srsName The SRS to write in output GML
* @return The GML v2 content
* @throws Exception A generic exception thrown in parsing
*/
public static String parseToGML2(String input, String srsName) throws Exception {
return GMLWriter.getGML(parse(input), 2, srsName);
}
/** Method to parse a WKT string to get GML 3 output (for example MultiSurface instead of MultiPolygon).<br/><br/>
* @param input The WKT string
* @return The GML v3 content
* @throws Exception A generic exception thrown in parsing
*/
public static String parseToGML3(String input) throws Exception {
return GMLWriter.getGML(parse(input), 3, null);
}
/** Method to parse a WKT string to get GML 3 output (for example MultiSurface instead of MultiPolygon).<br/><br/>
* @param input The WKT string
* @param srsName The SRS to write in output GML
* @return The GML v3 content
* @throws Exception A generic exception thrown in parsing
*/
public static String parseToGML3(String input, String srsName) throws Exception {
return GMLWriter.getGML(parse(input), 3, srsName);
}
/** Method to parse a WKT string.<br/><br/>
* @param input The WKT string
* @return The An AbstractGeometry object (instance of Point, or MultiPoint, or LineString, or MultiLineString, or Polygon, or MultiPolygon)
* @throws Exception A generic exception thrown in parsing
*/
public static AbstractGeometry parse(String input) throws Exception {
AbstractGeometry result;
if(input == null || !input.trim().matches("^(\\w+)(\\sZ){0,1}\\s*\\(\\s*(.*)\\s*\\)$")) {
throw new Exception("Invalid input");
}
/**
* @author Jones
* @change: toUpperCase added to the s variable, to avoid errors with
* geometries annotated with lower case literals, e.g. Point, point.
*/
String s = input.substring(0, input.indexOf('(')).trim().toUpperCase();
String content = input.substring(input.indexOf('(') + 1, input.lastIndexOf(')'));
if(s.equals("POINT")) {
result = pointFromWkt(content, 2);
}
else if(s.equals("POINTZ") || s.equals("POINT Z")) {
result = pointFromWkt(content, 3);
}
else if(s.equals("MULTIPOINT")) {
result = multiPointFromWkt(content, 2);
}
else if(s.equals("MULTIPOINTZ") || s.equals("MULTIPOINT Z")) {
result = multiPointFromWkt(content, 3);
}
else if(s.equals("LINESTRING")) {
result = lineStringFromWkt(content, 2);
}
else if(s.equals("LINESTRINGZ") || s.equals("LINESTRING Z")) {
result = lineStringFromWkt(content, 3);
}
else if(s.equals("MULTILINESTRING")) {
result = multiLineStringFromWkt(content, 2);
}
else if(s.equals("MULTILINESTRINGZ") || s.equals("MULTILINESTRING Z")) {
result = multiLineStringFromWkt(content, 3);
}
else if(s.equals("POLYGON")) {
result = polygonFromWkt(content, 2);
}
else if(s.equals("POLYGONZ") || s.equals("POLYGON Z")) {
result = polygonFromWkt(content, 3);
}
else if(s.equals("MULTIPOLYGON")) {
result = multiPolygonFromWkt(content, 2);
}
else if(s.equals("MULTIPOLYGONZ") || s.equals("MULTIPOLYGON Z")) {
result = multiPolygonFromWkt(content, 3);
}
else {
throw new Exception("Invalid input");
}
return result;
}
private static Point pointFromWkt(String input, int dims) throws Exception {
Point result;
List<String> coords = StringUtils.splitSpaces(input);
if(coords.size() != dims) {
throw new Exception("Invalid dimension");
}
if(dims == 3) {
result = new Point(Double.parseDouble(coords.get(0)), Double.parseDouble(coords.get(1)), Double.parseDouble(coords.get(2)));
}
else {
result = new Point(Double.parseDouble(coords.get(0)), Double.parseDouble(coords.get(1)));
}
return result;
}
private static MultiPoint multiPointFromWkt(String input, int dims) throws Exception {
List<String> parts = StringUtils.splitCommas(input);
List<Point> points = new ArrayList<Point>();
Point p;
for(int i = 0; i < parts.size(); i++) {
p = pointFromWkt(parts.get(i), dims);
if(p.getDimensions() != dims) {
throw new Exception("Invalid dimension");
}
points.add(p);
}
return new MultiPoint(points);
}
private static LineString lineStringFromWkt(String input, int dims) throws Exception {
List<String> parts = StringUtils.splitCommas(input);
List<Point> points = new ArrayList<Point>();
Point p;
for(int i = 0; i < parts.size(); i++) {
p = pointFromWkt(parts.get(i), dims);
if(p.getDimensions() != dims) {
throw new Exception("Invalid dimension");
}
points.add(p);
}
return new LineString(points);
}
private static MultiLineString multiLineStringFromWkt(String input, int dims) throws Exception {
List<String> parts = StringUtils.splitParentCommas(input);
List<LineString> lineStrings = new ArrayList<LineString>();
LineString ls;
for(int i = 0; i < parts.size(); i++) {
ls = lineStringFromWkt(parts.get(i), dims);
if(ls.getDimensions() != dims) {
throw new Exception("Invalid dimension");
}
lineStrings.add(ls);
}
return new MultiLineString(lineStrings);
}
private static Polygon polygonFromWkt(String input, int dims) throws Exception {
List<String> parts = StringUtils.splitParentCommas(input);
List<MultiPoint> multiPoints = new ArrayList<MultiPoint>();
MultiPoint mp;
for(int i = 0; i < parts.size(); i++) {
mp = multiPointFromWkt(parts.get(i), dims);
if(mp.getDimensions() != dims) {
throw new Exception("Invalid dimension");
}
multiPoints.add(mp);
}
return new Polygon(multiPoints);
}
private static MultiPolygon multiPolygonFromWkt(String input, int dims) throws Exception {
List<String> parts = StringUtils.splitDoubleParentCommas(input);
List<Polygon> polygons = new ArrayList<Polygon>();
Polygon p;
for(int i = 0; i < parts.size(); i++) {
p = polygonFromWkt("(" + parts.get(i) + ")", dims);
if(p.getDimensions() != dims) {
throw new Exception("Invalid dimension");
}
polygons.add(p);
}
return new MultiPolygon(polygons);
}
}