]> granicus.if.org Git - postgis/commitdiff
Added BOX2D and BOX3D support and tests, by Markus Shaber.
authorSandro Santilli <strk@keybit.net>
Sun, 30 Jan 2005 09:46:46 +0000 (09:46 +0000)
committerSandro Santilli <strk@keybit.net>
Sun, 30 Jan 2005 09:46:46 +0000 (09:46 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@1354 b70326c6-7e19-0410-871a-916f4a2858ee

jdbc2/Makefile
jdbc2/src/examples/TestBoxes.java [new file with mode: 0644]
jdbc2/src/org/postgis/DriverWrapper.java
jdbc2/src/org/postgis/PGbox2d.java [new file with mode: 0644]
jdbc2/src/org/postgis/PGbox3d.java
jdbc2/src/org/postgis/PGboxbase.java [new file with mode: 0644]

index 4bc218cc2d15d5cd1928d7ac55e78798fc29f7c1..bc079b591d8eaa643ae6786dccdaefe1a0d34ebe 100644 (file)
@@ -23,6 +23,7 @@ PGUSER?=psql
 PGPASS?=guess
 
 SRC= $(SRCDIR)/examples/Test.java \
+               $(SRCDIR)/examples/TestBoxes.java \
                $(SRCDIR)/examples/TestParser.java \
                $(SRCDIR)/examples/TestServer.java \
                $(SRCDIR)/org/postgis/ComposedGeom.java \
@@ -34,8 +35,8 @@ SRC= $(SRCDIR)/examples/Test.java \
                $(SRCDIR)/org/postgis/MultiLineString.java \
                $(SRCDIR)/org/postgis/MultiPoint.java \
                $(SRCDIR)/org/postgis/MultiPolygon.java \
+               $(SRCDIR)/org/postgis/PGbox2d.java \
                $(SRCDIR)/org/postgis/PGbox3d.java \
-               $(SRCDIR)/org/postgis/PGbox.java \
                $(SRCDIR)/org/postgis/PGgeometry.java \
                $(SRCDIR)/org/postgis/PointComposedGeom.java \
                $(SRCDIR)/org/postgis/Point.java \
@@ -43,7 +44,7 @@ SRC= $(SRCDIR)/examples/Test.java \
 
 
 all:   jar \
-       test
+       offlinetests
 
 jar:   compile
        $(JAR) -cf postgis.jar -C $(BUILD) . -C $(SRCDIR) org/postgresql/postgresql.properties README   
@@ -70,6 +71,20 @@ ptestoffline: compile
 ptest:  compile
        $(JAVA) -classpath "$(BUILD):$(CP)" $(EXAMPLES)/TestParser jdbc:postgresql_postGIS://$(PGHOST):$(PGPORT)/$(PGDATABASE) $(PGUSER) $(PGPASS)
 
+boxtestoffline: compile        
+       $(JAVA) -classpath "$(BUILD):$(CP)" $(EXAMPLES)/TestBoxes offline
+
+boxtest:  compile
+       $(JAVA) -classpath "$(BUILD):$(CP)" $(EXAMPLES)/TestBoxes jdbc:postgresql_postGIS://$(PGHOST):$(PGPORT)/$(PGDATABASE) $(PGUSER) $(PGPASS)
+
+offlinetests: boxtestoffline ptestoffline test
+
+onlinetests: boxtest ptest jtest
+
+# boxtest and ptest include boxtestoffline and ptestoffline, so we only need
+# to run test in addition to the onlinetests
+alltests: onlinetests test
+
 clean:  
        $(DELETE) $(BUILD) bin postgis.jar postgis_debug.jar compile
      
diff --git a/jdbc2/src/examples/TestBoxes.java b/jdbc2/src/examples/TestBoxes.java
new file mode 100644 (file)
index 0000000..1f87557
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Test client and server side Parsing of canonical text representations, as
+ * well as the PostGisWrapper jdbc extension.
+ *
+ * (C) 2005 Markus Schaber, logi-track ag, Zürich, Switzerland
+ *
+ * This file is licensed under the GNU GPL. *** put full notice here ***
+ *
+ * $Id$
+ */
+
+package examples;
+
+import org.postgis.PGbox2d;
+import org.postgis.PGbox3d;
+import org.postgresql.util.PGobject;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class TestBoxes {
+
+    /** Our test candidates: */
+    public static final String[] BOXEN3D = new String[]{
+        "BOX3D(1 2 3,4 5 6)", //3d variant
+        "BOX3D(1 2,4 5)"// 2d variant
+    };
+    public static final String[] BOXEN2D = new String[]{"BOX(1 2,3 4)"};
+
+    /** 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 orig, PGobject candidate, Connection[] conns)
+            throws SQLException {
+
+        System.out.println("Original:  " + orig);
+        String redone = candidate.toString();
+        System.out.println("Parsed:    " + redone);
+
+        if (!orig.equals(redone)) {
+            System.out.println("--- Recreated Text Rep not equal!");
+            failcount++;
+        }
+
+        // Let's simulate the way pgjdbc uses to create PGobjects
+        PGobject recreated;
+        try {
+            recreated = (PGobject) candidate.getClass().newInstance();
+        } catch (Exception e) {
+            System.out.println("--- pgjdbc instantiation failed!");
+            System.out.println("--- " + e.getMessage());
+            failcount++;
+            return;
+        }
+        recreated.setValue(redone);
+
+        String reparsed = recreated.toString();
+        System.out.println("Re-Parsed: " + reparsed);
+        if (!recreated.equals(candidate)) {
+            System.out.println("--- Recreated boxen are not equal!");
+            failcount++;
+        } else if (!reparsed.equals(orig)) {
+            System.out.println("--- 2nd generation 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 {
+                PGobject sqlGeom = viaSQL(candidate, statement);
+                System.out.println("SQLin    : " + sqlGeom.toString());
+                if (!candidate.equals(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 {
+                PGobject sqlreGeom = viaSQL(recreated, statement);
+                System.out.println("SQLout  :  " + sqlreGeom.toString());
+                if (!candidate.equals(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("***");
+    }
+
+    /** Pass a geometry representation through the SQL server */
+    private static PGobject viaSQL(PGobject obj, Statement stat) throws SQLException {
+        ResultSet rs = stat.executeQuery("SELECT '" + obj.toString() + "'::" + obj.getType());
+        rs.next();
+        return (PGobject) rs.getObject(1);
+    }
+
+    /**
+     * 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.DriverWrapper");
+        conn = DriverManager.getConnection(url, dbuser, dbpass);
+        return conn;
+    }
+
+    /** Our apps entry point */
+    public static void main(String[] args) throws SQLException, ClassNotFoundException {
+        String[] dburls;
+        String dbuser = null;
+        String dbpass = null;
+
+        if (args.length == 1 && args[0].equalsIgnoreCase("offline")) {
+            System.out.println("Performing only offline tests");
+            dburls = new String[0];
+        } else if (args.length == 3) {
+            System.out.println("Performing offline and online tests");
+            dburls = args[0].split(";");
+            dbuser = args[1];
+            dbpass = args[2];
+        } else {
+            System.err.println("Usage: java examples/TestParser dburls user pass [tablename]");
+            System.err.println("   or: java examples/TestParser 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.
+            throw new AssertionError();
+        }
+
+        Connection[] conns;
+        conns = new Connection[dburls.length];
+        for (int i = 0; i < dburls.length; i++) {
+            System.out.println("Creating JDBC connection to " + dburls[i]);
+            conns[i] = connect(dburls[i], dbuser, dbpass);
+        }
+
+        System.out.println("Performing tests...");
+        System.out.println("***");
+
+        for (int i = 0; i < BOXEN3D.length; i++) {
+            try {
+                PGbox3d candidate = new PGbox3d(BOXEN3D[i]);
+                test(BOXEN3D[i], candidate, conns);
+            } catch (SQLException e) {
+                System.out.println("--- Instantiation of " + BOXEN3D[i] + "failed:");
+                System.out.println("--- " + e.getMessage());
+                failcount++;
+            }
+        }
+
+        for (int i = 0; i < BOXEN2D.length; i++) {
+            try {
+                PGbox2d candidate = new PGbox2d(BOXEN2D[i]);
+                test(BOXEN2D[i], candidate, conns);
+            } catch (SQLException e) {
+                System.out.println("--- Instantiation of " + BOXEN2D[i] + "failed:");
+                System.out.println("--- " + e.getMessage());
+                failcount++;
+            }
+        }
+
+        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
index d50e7212fbe806ff2445ac84fe63564153b08370..56afa1331d0e9c06d4cca87fd119fd5ead4c2be6 100644 (file)
@@ -107,13 +107,15 @@ public class DriverWrapper extends Driver {
         // This is correct for PostgreSQL jdbc drivers up to V7.4
         pgconn.addDataType("geometry", "org.postgis.PGgeometry");
         pgconn.addDataType("box3d", "org.postgis.PGbox3d");
-        pgconn.addDataType("box3d", "org.postgis.PGbox");
+        pgconn.addDataType("box2d", "org.postgis.PGbox2d");
+
         // If you use PostgreSQL jdbc drivers V8.0 or newer, the above
         // methods are deprecated (but still work for now), and you
         // may want to use the two lines below instead.
+
         //pgconn.addDataType("geometry", org.postgis.PGgeometry.class);
         //pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
-        //pgconn.addDataType("box3d", org.postgis.PGBox.class);
+        //pgconn.addDataType("box2d", org.postgis.PGbox2d.class);
     }
 
     /**
diff --git a/jdbc2/src/org/postgis/PGbox2d.java b/jdbc2/src/org/postgis/PGbox2d.java
new file mode 100644 (file)
index 0000000..be3b714
--- /dev/null
@@ -0,0 +1,38 @@
+package org.postgis;
+
+import java.sql.SQLException;
+
+public class PGbox2d extends PGboxbase {
+
+    public PGbox2d() {
+        super();
+    }
+
+    public PGbox2d(Point llb, Point urt) {
+        super(llb, urt);
+    }
+
+    public PGbox2d(String value) throws SQLException {
+        super(value);
+    }
+
+    public void setValue(String value) throws SQLException {
+        super.setValue(value);
+
+        if (llb.dimension!=2 || urt.dimension!=2) {
+            throw new SQLException("PGbox2d is only allowed to have 2 dimensions!");
+        }
+    }
+
+    public String getPrefix() {
+        return "BOX";
+    }
+
+    public String getPGtype() {
+        return "box2d";
+    }
+
+    protected PGboxbase newInstance() {
+        return new PGbox2d();
+    }
+}
index 8d3d5d2df9b612a8197c42b43eee995f8b8175b9..70141fd7af1c1a0494a198c3f9dd969e8fb3be3c 100644 (file)
@@ -1,72 +1,29 @@
 package org.postgis;
 
-import org.postgresql.util.PGobject;
-import org.postgresql.util.PGtokenizer;
-
 import java.sql.SQLException;
 
-/*
- * Updates Oct 2002 - data members made private - getLLB() and getURT() methods
- * added
- */
-
-public class PGbox3d extends PGobject {
-
-    /**
-     * The lower left bottom corner of the box.
-     */
-    private Point llb;
-
-    /**
-     * The upper right top corner of the box.
-     */
-    private Point urt;
-
+public class PGbox3d extends PGboxbase {
     public PGbox3d() {
-        // do nothing.
+        super();
     }
 
     public PGbox3d(Point llb, Point urt) {
-        this.llb = llb;
-        this.urt = urt;
+        super(llb, urt);
     }
 
     public PGbox3d(String value) throws SQLException {
-        setValue(value);
-    }
-
-    public void setValue(String value) throws SQLException {
-        value = value.trim();
-        if (value.startsWith("BOX3D")) {
-            value = value.substring(5);
-        }
-        PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(value.trim()), ',');
-        llb = new Point(t.getToken(0));
-        urt = new Point(t.getToken(1));
-    }
-
-    public String getValue() {
-        return "BOX3D (" + llb.getValue() + "," + urt.getValue() + ")";
+        super(value);
     }
 
-    public String toString() {
-        return getValue();
+    public String getPrefix() {
+        return ("BOX3D");
     }
 
-    public Object clone() {
-        PGbox3d obj = new PGbox3d(llb, urt);
-        obj.setType(type);
-        return obj;
+    public String getPGtype() {
+        return ("box3d");
     }
 
-    /** Returns the lower left bottom corner of the box as a Point object */
-    public Point getLLB() {
-        return llb;
+    protected PGboxbase newInstance() {
+        return new PGbox3d();
     }
-
-    /** Returns the upper right top corner of the box as a Point object */
-    public Point getURT() {
-        return urt;
-    }
-
-}
\ No newline at end of file
+}
diff --git a/jdbc2/src/org/postgis/PGboxbase.java b/jdbc2/src/org/postgis/PGboxbase.java
new file mode 100644 (file)
index 0000000..3b31bf9
--- /dev/null
@@ -0,0 +1,144 @@
+package org.postgis;
+
+import org.postgresql.util.PGobject;
+import org.postgresql.util.PGtokenizer;
+
+import java.sql.SQLException;
+
+/*
+ * Updates Oct 2002 - data members made private - getLLB() and getURT() methods
+ * added
+ */
+
+public abstract class PGboxbase extends PGobject {
+
+    /**
+     * The lower left bottom corner of the box.
+     */
+    protected Point llb;
+
+    /**
+     * The upper right top corner of the box.
+     */
+    protected Point urt;
+
+    /**
+     * The Prefix we have in WKT rep.
+     *
+     * I use an abstract method here so we do not need to replicate the String
+     * object in every instance.
+     *
+     */
+    public abstract String getPrefix();
+
+    /**
+     * The Postgres type we have (same construct as getPrefix())
+     */
+    public abstract String getPGtype();
+
+    public PGboxbase() {
+        this.setType(getPGtype());
+    }
+
+    public PGboxbase(Point llb, Point urt) {
+        this();
+        this.llb = llb;
+        this.urt = urt;
+    }
+
+    public PGboxbase(String value) throws SQLException {
+        this();
+        setValue(value);
+    }
+
+    public void setValue(String value) throws SQLException {
+        int srid = -1;
+        value = value.trim();
+        if (value.startsWith("SRID=")) {
+            String[] temp = value.split(";", 2);
+            value = temp[1].trim();
+            srid = Integer.parseInt(temp[0].substring(5));
+        }
+        if (value.startsWith(getPrefix())) {
+            value = value.substring(getPrefix().length());
+        }
+        PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(value.trim()), ',');
+        llb = new Point(t.getToken(0));
+        urt = new Point(t.getToken(1));
+        if (srid != -1) {
+            llb.setSrid(srid);
+            urt.setSrid(srid);
+        }
+    }
+
+    public String getValue() {
+        StringBuffer sb = new StringBuffer();
+        outerWKT(sb);
+        return sb.toString();
+    }
+
+    private void outerWKT(StringBuffer sb) {
+        sb.append(getPrefix());
+        sb.append('(');
+        llb.innerWKT(sb);
+        sb.append(',');
+        urt.innerWKT(sb);
+        sb.append(')');
+    }
+
+    /**
+     * Unlike geometries, toString() does _not_ contain the srid, as server-side
+     * PostGIS cannot parse this.
+     */
+    public String toString() {
+        return getValue();
+    }
+
+    /** Returns the lower left bottom corner of the box as a Point object */
+    public Point getLLB() {
+        return llb;
+    }
+
+    /** Returns the upper right top corner of the box as a Point object */
+    public Point getURT() {
+        return urt;
+    }
+
+    public boolean equals(Object other) {
+        if (other instanceof PGboxbase) {
+            PGboxbase otherbox = (PGboxbase) other;
+            return (compareLazyDim(this.llb, otherbox.llb) && compareLazyDim(this.urt, otherbox.urt));
+        }
+        return false;
+    }
+
+    /**
+     * Compare two coordinates with lazy dimension checking.
+     *
+     * As the Server always returns Box3D with three dimensions, z==0 equals
+     * dimensions==2
+     *
+     */
+    protected static boolean compareLazyDim(Point first, Point second) {
+        return first.x == second.x
+                && first.y == second.y
+                && (((first.dimension == 2 || first.z == 0.0) && (second.dimension == 2 || second.z == 0)) || (first.z == second.z));
+    }
+
+    public Object clone() {
+        PGboxbase obj = newInstance();
+        obj.llb = this.llb;
+        obj.urt = this.urt;
+        obj.setType(type);
+        return obj;
+    }
+
+    /**
+     * We could have used this.getClass().newInstance() here, but this forces us
+     * dealing with InstantiationException and IllegalAccessException. Due to
+     * the PGObject.clone() brokennes that does not allow clone() to throw
+     * CloneNotSupportedException, we cannot even pass this exceptions down to
+     * callers in a sane way.
+     */
+    protected abstract PGboxbase newInstance();
+}