failures on simple (single) geometry types.
- jdbc2: slightly updated makefile
- plugged a leak in GEOS2POSTGIS converter
+ - jdbc2: added BETA support for jts geometry classes
PostGIS 1.0.0RC2
2005/01/26
postgis_debug.jar
stubbin
stubcompile
+jtscompile
STUBDIR=stubs
STUBBUILD=stubbin/
STUBSRC= $(STUBDIR)/org/postgresql/Connection.java \
- $(STUBDIR)/org/postgresql/PGConnection.java
+ $(STUBDIR)/org/postgresql/PGConnection.java
+
+JTSDIR=jtssrc
+JTSBUILD=jtsbin/
+JTSSRC= $(JTSDIR)/examples/JtsTestParser.java \
+ $(JTSDIR)/org/postgis/jts/JtsBinaryParser.java \
+ $(JTSDIR)/org/postgis/jts/JtsGeometry.java \
+ $(JTSDIR)/org/postgis/jts/JtsGisWrapper.java \
+ $(JTSDIR)/org/postgis/jts/JtsWrapper.java \
+
# Now the makefile targets that do the work:
alltests: onlinetests test
clean:
- $(DELETE) $(BUILD) bin stubbin postgis.jar postgis_debug.jar compile stubcompile
+ $(DELETE) $(BUILD) bin stubbin postgis.jar postgis_debug.jar \
+ compile stubcompile jtscompile $(JTSBUILD) postgis_jts.jar
# The following two targets are needed for debian build, but may be hepful
# for someone else, too.
@echo Testing for successful inclusion of $(top_makefile)
test $(DESTDIR)
$(mkinstalldirs) $(DESTDIR)
+
+# Preliminary JTS support
+
+postgis_jts: postgis_jts.jar jtstestoffline
+ @echo "Warning! This is beta code. Use at your own risk."
+
+$(JTSBUILD):
+ $(MKDIR) $(JTSBUILD)
+
+
+jtscompile: compile stubcompile $(JTSBUILD) $(JTSSRC)
+ $(JAVAC) -classpath "$(BUILD):$(CP)" -d $(JTSBUILD) $(JTSSRC)
+ touch jtscompile
+
+jtstestoffline: jtscompile
+ $(JAVA) -classpath "$(JTSBUILD):$(BUILD):$(CP)" $(EXAMPLES)/JtsTestParser offline
+
+jtstest: jtscompile
+ $(JAVA) -classpath "$(JTSBUILD):$(BUILD):$(CP)" $(EXAMPLES)/JtsTestParser jdbc:postgres_jts://$(PGHOST):$(PGPORT)/$(PGDATABASE) $(PGUSER) $(PGPASS)
+
+postgis_jts.jar: jtscompile $(SRCDIR)/org/postgresql/driverconfig.properties
+ $(JAR) -cf postgis_jts.jar -C $(BUILD) . \
+ -C $(SRCDIR) org/postgresql/driverconfig.properties \
+ README COPYING_LGPL -C .. COPYING
+ $(JAR) -uf postgis_jts.jar -C $(JTSBUILD) .
+
+
+
\ No newline at end of file
the PostGIS developer list.
+* What about the JTS stuff *
+
+There's beta support for the JTS 1.6 geometry implementations instead of the
+native PostGIS classes on the java client side. Simply add jts_1.6.jar to your
+CLASSPATH, "make postgis_jts" and use at your own risk.
+
+
* Phew. That's all? *
Yes. For now, at least.
--- /dev/null
+/*
+ * Test.java
+ *
+ * PostGIS extension for PostgreSQL JDBC driver - example and test classes
+ *
+ * (C) 2004 Paul Ramsey, pramsey@refractions.net
+ *
+ * (C) 2005 Markus Schaber, schabios@logi-track.com
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License.
+ *
+ * This program 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA or visit the web at
+ * http://www.gnu.org.
+ *
+ * $Id$
+ */
+
+package examples;
+
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.io.WKTReader;
+
+import org.postgis.jts.JtsGeometry;
+import org.postgresql.util.PGtokenizer;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class JtsTestParser {
+ final static WKTReader reader = new WKTReader();
+
+ /**
+ * Our set of geometries to test.
+ */
+ public static final String[] testset = new String[]{
+ "POINT(10 10 20)",
+ "MULTIPOINT(10 10 10, 20 20 20)",
+ "LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34)",
+ "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
+ "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
+ "MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
+ "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))",
+ "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))",
+ "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
+ "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))",
+ "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
+ "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))",
+ "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
+ "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
+ "GEOMETRYCOLLECTION EMPTY", // new (correct) representation
+ "POINT EMPTY", // new (correct) representation
+ "LINESTRING EMPTY", // new (correct) representation
+ "POLYGON EMPTY", // new (correct) representation
+ "MULTIPOINT EMPTY", // new (correct) representation
+ "MULTILINESTRING EMPTY", // new (correct) representation
+ "MULTIPOLYGON EMPTY", // new (correct) representation
+ };
+
+ /** The srid we use for the srid tests */
+ public static final int SRID = 4326;
+
+ /** The string prefix we get for the srid tests */
+ public static final String SRIDPREFIX = "SRID=" + SRID + ";";
+
+ /** How much tests did fail? */
+ public static int failcount = 0;
+
+ /** The actual test method */
+ public static void test(String WKT, Connection[] conns) throws SQLException {
+ System.out.println("Original: " + WKT);
+ Geometry geom = JtsGeometry.geomFromString(WKT);
+ String parsed = geom.toString();
+ System.out.println("Parsed: " + parsed);
+ Geometry regeom = JtsGeometry.geomFromString(parsed);
+ String reparsed = regeom.toString();
+ System.out.println("Re-Parsed: " + reparsed);
+ if (safeGeomUnequal(geom, regeom)) {
+ System.out.println("--- Geometries are not equal!");
+ failcount++;
+ } else if (!reparsed.equals(parsed)) {
+ System.out.println("--- Text Reps are not equal!");
+ failcount++;
+ } else {
+ System.out.println("Equals: yes");
+ }
+ for (int i = 0; i < conns.length; i++) {
+ System.out.println("Testing on connection " + i + ": " + conns[i].getCatalog());
+ Statement statement = conns[i].createStatement();
+
+ try {
+ Geometry sqlGeom = viaSQL(WKT, statement);
+ System.out.println("SQLin : " + sqlGeom.toString());
+ if (safeGeomUnequal(geom, sqlGeom)) {
+ System.out.println("--- Geometries after SQL are not equal!");
+ failcount++;
+ } else {
+ System.out.println("Eq SQL in: yes");
+ }
+ } catch (SQLException e) {
+ System.out.println("--- Server side error: " + e.toString());
+ failcount++;
+ }
+
+ try {
+ Geometry sqlreGeom = viaSQL(parsed, statement);
+ System.out.println("SQLout : " + sqlreGeom.toString());
+ if (safeGeomUnequal(geom, sqlreGeom)) {
+ System.out.println("--- reparsed Geometries after SQL are not equal!");
+ failcount++;
+ } else {
+ System.out.println("Eq SQLout: yes");
+ }
+ } catch (SQLException e) {
+ System.out.println("--- Server side error: " + e.toString());
+ failcount++;
+ }
+
+ statement.close();
+ }
+ System.out.println("***");
+ }
+
+ private static boolean safeGeomUnequal(Geometry geom, Geometry regeom) {
+ try {
+ return !geom.equals(regeom);
+ } catch (java.lang.IllegalArgumentException e) {
+ System.out.println(".equals call failed: " + e.getMessage());
+ return false;
+ }
+ }
+
+ /** Pass a geometry representation through the SQL server */
+ private static Geometry viaSQL(String rep, Statement stat) throws SQLException {
+ ResultSet rs = stat.executeQuery("SELECT geometry_in('" + rep + "')");
+ rs.next();
+ return ((JtsGeometry) rs.getObject(1)).getGeometry();
+ }
+
+ /**
+ * Connect to the databases
+ *
+ * We use DriverWrapper here. For alternatives, see the DriverWrapper
+ * Javadoc
+ *
+ * @param dbuser
+ *
+ * @throws ClassNotFoundException
+ *
+ * @see org.postgis.DriverWrapper
+ *
+ */
+ public static Connection connect(String url, String dbuser, String dbpass) throws SQLException,
+ ClassNotFoundException {
+ Connection conn;
+ Class.forName("org.postgis.jts.JtsWrapper");
+ conn = DriverManager.getConnection(url, dbuser, dbpass);
+ return conn;
+ }
+
+ /** Our apps entry point */
+ public static void main(String[] args) throws SQLException, ClassNotFoundException {
+ PGtokenizer dburls;
+ String dbuser = null;
+ String dbpass = null;
+
+ if (args.length == 1 && args[0].equalsIgnoreCase("offline")) {
+ System.out.println("Performing only offline tests");
+ dburls = new PGtokenizer("", ';');
+ } else if (args.length == 3) {
+ System.out.println("Performing offline and online tests");
+ dburls = new PGtokenizer(args[0], ';');
+
+ dbuser = args[1];
+ dbpass = args[2];
+ } else {
+ System.err.println("Usage: java examples/JtsTestParser dburls user pass [tablename]");
+ System.err.println(" or: java examples/JtsTestParser offline");
+ System.err.println();
+ System.err.println("dburls has one or more jdbc urls separated by ; in the following format");
+ System.err.println("jdbc:postgresql://HOST:PORT/DATABASENAME");
+ System.err.println("tablename is 'jdbc_test' by default.");
+ System.exit(1);
+ // Signal the compiler that code flow ends here.
+ return;
+ }
+
+ Connection[] conns;
+ conns = new Connection[dburls.getSize()];
+ for (int i = 0; i < dburls.getSize(); i++) {
+ System.out.println("Creating JDBC connection to " + dburls.getToken(i));
+ conns[i] = connect(dburls.getToken(i), dbuser, dbpass);
+ }
+
+ System.out.println("Performing tests...");
+ System.out.println("***");
+
+ for (int i = 0; i < testset.length; i++) {
+ test(testset[i], conns);
+ test(SRIDPREFIX + testset[i], conns);
+ }
+
+ System.out.print("cleaning up...");
+ for (int i = 0; i < conns.length; i++) {
+ conns[i].close();
+ }
+
+ //System.out.println("Finished.");
+ System.out.println("Finished, " + failcount + " tests failed!");
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * JtsBinaryParser.java
+ *
+ * Binary Parser for JTS - relies on org.postgis V1.0.0+ package.
+ *
+ * (C) 2005 Markus Schaber, schabios@logi-track.com
+ *
+ * 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.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit the web at
+ * http://www.gnu.org.
+ *
+ * $Id$
+ */
+package org.postgis.jts;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.CoordinateSequence;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.GeometryCollection;
+import com.vividsolutions.jts.geom.GeometryFactory;
+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;
+import com.vividsolutions.jts.geom.impl.PackedCoordinateSequence;
+
+import org.postgis.binary.ByteGetter;
+import org.postgis.binary.ValueGetter;
+import org.postgis.binary.ByteGetter.BinaryByteGetter;
+import org.postgis.binary.ByteGetter.StringByteGetter;
+
+/**
+ * Parse binary representation of geometries. Currently, only text rep (hexed)
+ * implementation is tested.
+ *
+ * It should be easy to add char[] and CharSequence ByteGetter instances,
+ * although the latter one is not compatible with older jdks.
+ *
+ * I did not implement real unsigned 32-bit integers or emulate them with long,
+ * as both java Arrays and Strings currently can have only 2^31-1 elements
+ * (bytes), so we cannot even get or build Geometries with more than approx.
+ * 2^28 coordinates (8 bytes each).
+ *
+ * @author markus.schaber@logi-track.com
+ *
+ */
+public class JtsBinaryParser {
+ final static GeometryFactory geofac = new GeometryFactory();
+
+ /**
+ * Get the appropriate ValueGetter for my endianness
+ *
+ * @param bytes The appropriate Byte Getter
+ *
+ * @return the ValueGetter
+ */
+ public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
+ if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
+ return new ValueGetter.XDR(bytes);
+ } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
+ return new ValueGetter.NDR(bytes);
+ } else {
+ throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
+ }
+ }
+
+ /**
+ * Parse a hex encoded geometry
+ *
+ * Is synchronized to protect offset counter. (Unfortunately, Java does not
+ * have neither call by reference nor multiple return values.)
+ */
+ public synchronized Geometry parse(String value) {
+ StringByteGetter bytes = new ByteGetter.StringByteGetter(value);
+ return parseGeometry(valueGetterForEndian(bytes));
+ }
+
+ /**
+ * Parse a binary encoded geometry.
+ *
+ * Is synchronized to protect offset counter. (Unfortunately, Java does not
+ * have neither call by reference nor multiple return values.)
+ */
+ public synchronized Geometry parse(byte[] value) {
+ BinaryByteGetter bytes = new ByteGetter.BinaryByteGetter(value);
+ return parseGeometry(valueGetterForEndian(bytes));
+ }
+
+ /** Parse a geometry starting at offset. */
+ protected Geometry parseGeometry(ValueGetter data) {
+ byte endian = data.getByte(); //skip and test endian flag
+ if (endian != data.endian) {
+ throw new IllegalArgumentException("Endian inconsistency!");
+ }
+ int typeword = data.getInt();
+
+ int realtype = typeword & 0x1FFFFFFF; //cut off high flag bits
+
+ boolean haveZ = (typeword & 0x80000000) != 0;
+ boolean haveM = (typeword & 0x40000000) != 0;
+ boolean haveS = (typeword & 0x20000000) != 0;
+
+ int srid = -1;
+
+ if (haveS) {
+ srid = data.getInt();
+ }
+ Geometry result1;
+ switch (realtype) {
+ case org.postgis.Geometry.POINT :
+ result1 = parsePoint(data, haveZ, haveM);
+ break;
+ case org.postgis.Geometry.LINESTRING :
+ result1 = parseLineString(data, haveZ, haveM);
+ break;
+ case org.postgis.Geometry.POLYGON :
+ result1 = parsePolygon(data, haveZ, haveM);
+ break;
+ case org.postgis.Geometry.MULTIPOINT :
+ result1 = parseMultiPoint(data);
+ break;
+ case org.postgis.Geometry.MULTILINESTRING :
+ result1 = parseMultiLineString(data);
+ break;
+ case org.postgis.Geometry.MULTIPOLYGON :
+ result1 = parseMultiPolygon(data);
+ break;
+ case org.postgis.Geometry.GEOMETRYCOLLECTION :
+ result1 = parseCollection(data);
+ break;
+ default :
+ throw new IllegalArgumentException("Unknown Geometry Type!");
+ }
+
+ Geometry result = result1;
+
+ if (haveS) {
+ result.setSRID(srid);
+ }
+ return result;
+ }
+
+ private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
+ double X = data.getDouble();
+ double Y = data.getDouble();
+ Point result;
+ if (haveZ) {
+ double Z = data.getDouble();
+ result = geofac.createPoint(new Coordinate(X, Y, Z));
+ } else {
+ result = geofac.createPoint(new Coordinate(X, Y));
+ }
+
+ if (haveM) { //skip M value
+ data.getDouble();
+ }
+
+ return result;
+ }
+
+ /** Parse an Array of "full" Geometries */
+ private void parseGeometryArray(ValueGetter data, Geometry[] container) {
+ for (int i = 0; i < container.length; i++) {
+ container[i] = parseGeometry(data);
+ }
+ }
+
+ /**
+ * Parse an Array of "slim" Points (without endianness and type, part of
+ * LinearRing and Linestring, but not MultiPoint!
+ *
+ * @param haveZ
+ * @param haveM
+ */
+ private CoordinateSequence parseCS(ValueGetter data, boolean haveZ, boolean haveM) {
+ int count = data.getInt();
+ int dims = haveZ ? 3 : 2;
+ CoordinateSequence cs = new PackedCoordinateSequence.Double(count, dims);
+
+ for (int i = 0; i < count; i++) {
+ for (int d = 0; d < dims; d++) {
+ cs.setOrdinate(i, d, data.getDouble());
+ }
+ if (haveM) { //skip M value
+ data.getDouble();
+ }
+ }
+ return cs;
+ }
+
+ private MultiPoint parseMultiPoint(ValueGetter data) {
+ Point[] points = new Point[data.getInt()];
+ parseGeometryArray(data, points);
+ return geofac.createMultiPoint(points);
+ }
+
+ private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
+ return geofac.createLineString(parseCS(data, haveZ, haveM));
+ }
+
+ private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) {
+ return geofac.createLinearRing(parseCS(data, haveZ, haveM));
+ }
+
+ private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {
+ int holecount = data.getInt()-1;
+ LinearRing[] rings = new LinearRing[holecount];
+ LinearRing shell = parseLinearRing(data, haveZ, haveM);
+ for (int i = 0; i < holecount; i++) {
+ rings[i] = parseLinearRing(data, haveZ, haveM);
+ }
+ return geofac.createPolygon(shell, rings);
+ }
+
+ private MultiLineString parseMultiLineString(ValueGetter data) {
+ int count = data.getInt();
+ LineString[] strings = new LineString[count];
+ parseGeometryArray(data, strings);
+ return geofac.createMultiLineString(strings);
+ }
+
+ private MultiPolygon parseMultiPolygon(ValueGetter data) {
+ int count = data.getInt();
+ Polygon[] polys = new Polygon[count];
+ parseGeometryArray(data, polys);
+ return geofac.createMultiPolygon(polys);
+ }
+
+ private GeometryCollection parseCollection(ValueGetter data) {
+ int count = data.getInt();
+ Geometry[] geoms = new Geometry[count];
+ parseGeometryArray(data, geoms);
+ return geofac.createGeometryCollection(geoms);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * JtsGeometry.java
+ *
+ * Wrapper for PostgreSQL JDBC driver to allow transparent reading and writing
+ * of JTS geometries
+ *
+ * (C) 2005 Markus Schaber, schabios@logi-track.com
+ *
+ * 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.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit the web at
+ * http://www.gnu.org.
+ *
+ * $Id$
+ */
+
+package org.postgis.jts;
+
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.io.WKTReader;
+
+import org.postgresql.util.PGobject;
+
+import java.sql.SQLException;
+
+/**
+ * JTS Geometry SQL wrapper
+ *
+ * @author Markus Schaber
+ */
+
+public class JtsGeometry extends PGobject {
+
+ Geometry geom;
+
+ final static WKTReader reader = new WKTReader();
+ final static JtsBinaryParser bp = new JtsBinaryParser();
+
+
+ public JtsGeometry() {
+ //Constructor called by JDBC drivers
+ }
+
+ public JtsGeometry(Geometry geom) {
+ this.geom = geom;
+ }
+
+ public JtsGeometry(String value) throws SQLException {
+ setValue(value);
+ }
+
+ public void setValue(String value) throws SQLException {
+ geom = geomFromString(value);
+ }
+
+ public static Geometry geomFromString(String value) throws SQLException {
+ try {
+ value = value.trim();
+ if (value.startsWith("00") || value.startsWith("01")) {
+ return bp.parse(value);
+ } else {
+ Geometry result;
+ int srid = -1;
+ //break up geometry into srid and wkt
+ if (value.startsWith("SRID=")) {
+ String[] temp = value.split(";");
+ value = temp[1].trim();
+ srid = Integer.parseInt(temp[0].substring(5));
+ }
+ result = reader.read(value);
+ result.setSRID(srid);
+ return result;
+ }
+ } catch (Exception E) {
+ E.printStackTrace();
+ throw new SQLException("Error parsing SQL data:" + E);
+ }
+ }
+
+ public Geometry getGeometry() {
+ return geom;
+ }
+
+ public String toString() {
+ return geom.toString();
+ }
+
+ public String getValue() {
+ return geom.toString();
+ }
+
+ public Object clone() {
+ JtsGeometry obj = new JtsGeometry(geom);
+ obj.setType(type);
+ return obj;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof JtsGeometry)
+ return ((JtsGeometry) obj).getValue().equals(geom);
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * JtsWrapper.java
+ *
+ * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
+ * connected to a PostGIS enabled PostgreSQL server.
+ *
+ * (C) 2005 Markus Schaber, schabios@logi-track.com
+ *
+ * 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.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit the web at
+ * http://www.gnu.org.
+ *
+ * $Id$
+ */
+
+package org.postgis.jts;
+
+import org.postgresql.Driver;
+import org.postgresql.PGConnection;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+/**
+ * JtsGisWrapper
+ *
+ * Wraps the PostGreSQL Driver to add the JTS/PostGIS Object Classes.
+ *
+ * This method currently works with J2EE DataSource implementations, and with
+ * DriverManager framework.
+ *
+ * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_postGIS" in the
+ * jdbc URL.
+ *
+ * @author schabi
+ *
+ */
+public class JtsGisWrapper extends Driver {
+
+ private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
+ private static final String POSTGIS_PROTOCOL = "jdbc:postgresql_JTS:";
+ public static final String REVISION = "$Revision$";
+
+ public JtsGisWrapper() {
+ super();
+ }
+
+ static {
+ try {
+ // Analogy to org.postgresql.Driver
+ java.sql.DriverManager.registerDriver(new JtsGisWrapper());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a postgresql connection, and then adds the PostGIS data types to
+ * it calling addpgtypes()
+ *
+ * @param url the URL of the database to connect to
+ * @param info a list of arbitrary tag/value pairs as connection arguments
+ * @return a connection to the URL or null if it isnt us
+ * @exception SQLException if a database access error occurs
+ *
+ * @see java.sql.Driver#connect
+ * @see org.postgresql.Driver
+ */
+ public java.sql.Connection connect(String url, Properties info) throws SQLException {
+ url = mangleURL(url);
+ Connection result = super.connect(url, info);
+ addGISTypes((PGConnection) result);
+ return result;
+ }
+
+ /**
+ * adds the JTS/PostGIS Data types to a PG Connection.
+ */
+ public static void addGISTypes(PGConnection pgconn) {
+ pgconn.addDataType("geometry", "com.logitrack.gis.util.JtsGeometry");
+ pgconn.addDataType("box3d", "org.postgis.PGbox3d");
+ //pgconn.addDataType("geometry",
+ // com.logitrack.gis.util.JtsGeometry.class);
+ //pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
+ }
+
+ /**
+ * Mangles the PostGIS URL to return the original PostGreSQL URL
+ */
+ public static String mangleURL(String url) throws SQLException {
+ if (url.startsWith(POSTGIS_PROTOCOL)) {
+ return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
+ } else {
+ throw new SQLException("Unknown protocol or subprotocol in url " + url);
+ }
+ }
+
+ /**
+ * Returns true if the driver thinks it can open a connection to the given
+ * URL. Typically, drivers will return true if they understand the
+ * subprotocol specified in the URL and false if they don't. Our protocols
+ * start with jdbc:postgresql_postGIS:
+ *
+ * @see java.sql.Driver#acceptsURL
+ * @param url the URL of the driver
+ * @return true if this driver accepts the given URL
+ * @exception SQLException if a database-access error occurs (Dont know why
+ * it would *shrug*)
+ */
+ public boolean acceptsURL(String url) throws SQLException {
+ try {
+ url = mangleURL(url);
+ } catch (SQLException e) {
+ return false;
+ }
+ return super.acceptsURL(url);
+ }
+
+ /**
+ * Gets the underlying drivers major version number
+ *
+ * @return the drivers major version number
+ */
+
+ public int getMajorVersion() {
+ return super.getMajorVersion();
+ }
+
+ /**
+ * Get the underlying drivers minor version number
+ *
+ * @return the drivers minor version number
+ */
+ public int getMinorVersion() {
+ return super.getMinorVersion();
+ }
+
+ /**
+ * Returns our own CVS version plus postgres Version
+ */
+ public static String getVersion() {
+ return "JtsGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * JtsWrapper.java
+ *
+ * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
+ * connected to a PostGIS enabled PostgreSQL server.
+ *
+ * (C) 2005 Markus Schaber, schabios@logi-track.com
+ *
+ * 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.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit the web at
+ * http://www.gnu.org.
+ *
+ * $Id$
+ */
+
+package org.postgis.jts;
+
+import org.postgresql.Driver;
+import org.postgresql.PGConnection;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+/**
+ * DriverWrapper
+ *
+ * Wraps the PostGreSQL Driver to add the JTS/PostGIS Object Classes.
+ *
+ * This method currently works with J2EE DataSource implementations, and with
+ * DriverManager framework.
+ *
+ * Simply replace the "jdbc:postgresql:" with a "jdbc:postgres_jts:" in the jdbc
+ * URL.
+ *
+ * When using the drivermanager, you need to initialize JtsWrapper instead of
+ * (or in addition to) org.postgresql.Driver. When using a J2EE DataSource
+ * implementation, set the driver class property in the datasource config, the
+ * following works for jboss:
+ *
+ * <driver-class>com.logitrack.gis.util.PostGisWrapper</driver-class>
+ *
+ * @author schabi
+ *
+ */
+public class JtsWrapper extends Driver {
+
+ private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
+ private static final String POSTGIS_PROTOCOL = "jdbc:postgres_jts:";
+ public static final String REVISION = "$Revision$";
+
+ public JtsWrapper() {
+ super();
+ }
+
+ static {
+ try {
+ // Try to register ourself to the DriverManager
+ java.sql.DriverManager.registerDriver(new JtsWrapper());
+ } catch (SQLException e) {
+ Driver.info("Error registering PostgreSQL Jts Wrapper Driver", e);
+ }
+ }
+
+ /**
+ * Creates a postgresql connection, and then adds the JTS GIS data types to
+ * it calling addpgtypes()
+ *
+ * @param url the URL of the database to connect to
+ * @param info a list of arbitrary tag/value pairs as connection arguments
+ * @return a connection to the URL or null if it isnt us
+ * @exception SQLException if a database access error occurs
+ *
+ * @see java.sql.Driver#connect
+ * @see org.postgresql.Driver
+ */
+ public java.sql.Connection connect(String url, Properties info) throws SQLException {
+ url = mangleURL(url);
+ Connection result = super.connect(url, info);
+ addGISTypes((PGConnection) result);
+ return result;
+ }
+
+ /**
+ * adds the JTS/PostGIS Data types to a PG Connection.
+ */
+ public static void addGISTypes(PGConnection pgconn) {
+ // Add data type up to PostgreSQL jdbc driver V7.4
+ pgconn.addDataType("geometry", "org.postgis.jts.JtsGeometry");
+
+ // Use the following for PostgreSQL jdbc driver V8.0 or newer
+ // The above way still works, but is deprecated.
+ // pgconn.addDataType("geometry",
+ // com.logitrack.gis.util.JtsGeometry.class);
+ }
+
+ /**
+ * Mangles the PostGIS URL to return the original PostGreSQL URL
+ */
+ public static String mangleURL(String url) throws SQLException {
+ if (url.startsWith(POSTGIS_PROTOCOL)) {
+ return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
+ } else {
+ throw new SQLException("Unknown protocol or subprotocol in url " + url);
+ }
+ }
+
+ /**
+ * Check whether the driver thinks he can handle the given URL.
+ *
+ * @see java.sql.Driver#acceptsURL
+ * @param url the URL of the driver
+ * @return true if this driver accepts the given URL
+ * @exception SQLException Passed through from the underlying PostgreSQL
+ * driver, should not happen.
+ */
+ public boolean acceptsURL(String url) throws SQLException {
+ try {
+ url = mangleURL(url);
+ } catch (SQLException e) {
+ return false;
+ }
+ return super.acceptsURL(url);
+ }
+
+ /**
+ * Gets the underlying drivers major version number
+ *
+ * @return the drivers major version number
+ */
+
+ public int getMajorVersion() {
+ return super.getMajorVersion();
+ }
+
+ /**
+ * Get the underlying drivers minor version number
+ *
+ * @return the drivers minor version number
+ */
+ public int getMinorVersion() {
+ return super.getMinorVersion();
+ }
+
+ /**
+ * Returns our own CVS version plus postgres Version
+ */
+ public static String getVersion() {
+ return "JtsGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
+ }
+}
\ No newline at end of file