diff --git a/hibernate-spatial/COPYRIGHT b/hibernate-spatial/COPYRIGHT new file mode 100644 index 0000000000..63e19ed650 --- /dev/null +++ b/hibernate-spatial/COPYRIGHT @@ -0,0 +1,19 @@ + This file is part of Hibernate Spatial, an extension to the + hibernate ORM solution for spatial (geographic) data. + + Copyright © 2007-2012 Geovise BVBA + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + diff --git a/hibernate-spatial/databases/h2geodb/matrix.gradle b/hibernate-spatial/databases/h2geodb/matrix.gradle new file mode 100644 index 0000000000..7c28857548 --- /dev/null +++ b/hibernate-spatial/databases/h2geodb/matrix.gradle @@ -0,0 +1,2 @@ + +jdbcDependency "org.opengeo:geodb:0.6" \ No newline at end of file diff --git a/hibernate-spatial/databases/h2geodb/resources/hibernate.properties b/hibernate-spatial/databases/h2geodb/resources/hibernate.properties new file mode 100644 index 0000000000..61732216c3 --- /dev/null +++ b/hibernate-spatial/databases/h2geodb/resources/hibernate.properties @@ -0,0 +1,41 @@ +# +# Hibernate, Relational Persistence for Idiomatic Java +# +# Copyright (c) 2011, Red Hat Inc. or third-party contributors as +# indicated by the @author tags or express copyright attribution +# statements applied by the authors. All third-party contributions are +# distributed under license by Red Hat Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# Lesser General Public License, as published by the Free Software Foundation. +# +# 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 Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this distribution; if not, write to: +# Free Software Foundation, Inc. +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301 USA +# + +hibernate.dialect org.hibernate.spatial.dialect.h2geodb.GeoDBDialect +hibernate.connection.driver_class org.h2.Driver +hibernate.connection.url jdbc:h2:mem:testhbs;DB_CLOSE_DELAY=-1;MVCC=true +hibernate.connection.username sa +hibernate.connection.password sa + + +hibernate.connection.pool_size 5 + +hibernate.show_sql true +hibernate.format_sql true + +hibernate.max_fetch_depth 5 + +hibernate.cache.region_prefix hibernate.test +hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory + diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java new file mode 100644 index 0000000000..a4bd10aece --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java @@ -0,0 +1,287 @@ +/* + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for spatial (geographic) data. + * + * Copyright © 2007-2012 Geovise BVBA, Geodan IT b.v. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.hibernate.spatial.dialect.h2geodb; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.spatial.*; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +/** + * Extends the H2Dialect by also including information on spatial functions. + * + * @author Jan Boonen, Geodan IT b.v. + */ +public class GeoDBDialect extends H2Dialect implements SpatialDialect { + + /* + Contents of GeoDB's spatial registration script (geodb.sql): + + CREATE ALIAS AddGeometryColumn for "geodb.GeoDB.AddGeometryColumn" + CREATE ALIAS CreateSpatialIndex for "geodb.GeoDB.CreateSpatialIndex" + CREATE ALIAS DropGeometryColumn for "geodb.GeoDB.DropGeometryColumn" + CREATE ALIAS DropGeometryColumns for "geodb.GeoDB.DropGeometryColumns" + CREATE ALIAS DropSpatialIndex for "geodb.GeoDB.DropSpatialIndex" + CREATE ALIAS EnvelopeAsText for "geodb.GeoDB.EnvelopeAsText" + CREATE ALIAS GeometryType for "geodb.GeoDB.GeometryType" + CREATE ALIAS ST_Area FOR "geodb.GeoDB.ST_Area" + CREATE ALIAS ST_AsEWKB FOR "geodb.GeoDB.ST_AsEWKB" + CREATE ALIAS ST_AsEWKT FOR "geodb.GeoDB.ST_AsEWKT" + CREATE ALIAS ST_AsHexEWKB FOR "geodb.GeoDB.ST_AsHexEWKB" + CREATE ALIAS ST_AsText FOR "geodb.GeoDB.ST_AsText" + CREATE ALIAS ST_BBOX FOR "geodb.GeoDB.ST_BBox" + CREATE ALIAS ST_Buffer FOR "geodb.GeoDB.ST_Buffer" + CREATE ALIAS ST_Centroid FOR "geodb.GeoDB.ST_Centroid" + CREATE ALIAS ST_Crosses FOR "geodb.GeoDB.ST_Crosses" + CREATE ALIAS ST_Contains FOR "geodb.GeoDB.ST_Contains" + CREATE ALIAS ST_DWithin FOR "geodb.GeoDB.ST_DWithin" + CREATE ALIAS ST_Disjoint FOR "geodb.GeoDB.ST_Disjoint" + CREATE ALIAS ST_Distance FOR "geodb.GeoDB.ST_Distance" + CREATE ALIAS ST_Envelope FOR "geodb.GeoDB.ST_Envelope" + CREATE ALIAS ST_Equals FOR "geodb.GeoDB.ST_Equals" + CREATE ALIAS ST_GeoHash FOR "geodb.GeoDB.ST_GeoHash" + CREATE ALIAS ST_GeomFromEWKB FOR "geodb.GeoDB.ST_GeomFromEWKB" + CREATE ALIAS ST_GeomFromEWKT FOR "geodb.GeoDB.ST_GeomFromEWKT" + CREATE ALIAS ST_GeomFromText FOR "geodb.GeoDB.ST_GeomFromText" + CREATE ALIAS ST_GeomFromWKB FOR "geodb.GeoDB.ST_GeomFromWKB" + CREATE ALIAS ST_Intersects FOR "geodb.GeoDB.ST_Intersects" + CREATE ALIAS ST_IsEmpty FOR "geodb.GeoDB.ST_IsEmpty" + CREATE ALIAS ST_IsSimple FOR "geodb.GeoDB.ST_IsSimple" + CREATE ALIAS ST_IsValid FOR "geodb.GeoDB.ST_IsValid" + CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint" + CREATE ALIAS ST_MakeBox2D FOR "geodb.GeoDB.ST_MakeBox2D" + CREATE ALIAS ST_Overlaps FOR "geodb.GeoDB.ST_Overlaps" + CREATE ALIAS ST_SRID FOR "geodb.GeoDB.ST_SRID" + CREATE ALIAS ST_SetSRID FOR "geodb.GeoDB.ST_SetSRID" + CREATE ALIAS ST_Simplify FOR "geodb.GeoDB.ST_Simplify" + CREATE ALIAS ST_Touches FOR "geodb.GeoDB.ST_Touches" + CREATE ALIAS ST_Within FOR "geodb.GeoDB.ST_Within" + CREATE ALIAS Version FOR "geodb.GeoDB.Version" + */ + + /** + * Constructor. Registers OGC simple feature functions (see + * http://portal.opengeospatial.org/files/?artifact_id=829 for details). + *

+ * Note for the registerfunction method: it registers non-standard database + * functions: first argument is the internal (OGC standard) function name, + * second the name as it occurs in the spatial dialect + */ + public GeoDBDialect() { + super(); + + // Register Geometry column type + registerColumnType(java.sql.Types.ARRAY, "BLOB"); + + // Register functions that operate on spatial types +// NOT YET AVAILABLE IN GEODB +// registerFunction("dimension", new StandardSQLFunction("dimension", +// Hibernate.INTEGER)); + registerFunction("geometrytype", new StandardSQLFunction( + "GeometryType", StandardBasicTypes.STRING)); + registerFunction("srid", new StandardSQLFunction("ST_SRID", + StandardBasicTypes.INTEGER)); + registerFunction("envelope", new StandardSQLFunction("ST_Envelope", + GeometryType.INSTANCE)); + registerFunction("astext", new StandardSQLFunction("ST_AsText", + StandardBasicTypes.STRING)); + registerFunction("asbinary", new StandardSQLFunction("ST_AsEWKB", + StandardBasicTypes.BINARY)); + registerFunction("isempty", new StandardSQLFunction("ST_IsEmpty", + StandardBasicTypes.BOOLEAN)); + registerFunction("issimple", new StandardSQLFunction("ST_IsSimple", + StandardBasicTypes.BOOLEAN)); +// NOT YET AVAILABLE IN GEODB +// registerFunction("boundary", new StandardSQLFunction("boundary", +// new CustomType(GeoDBGeometryUserType.class, null))); + + // Register functions for spatial relation constructs + registerFunction("overlaps", new StandardSQLFunction("ST_Overlaps", + StandardBasicTypes.BOOLEAN)); + registerFunction("intersects", new StandardSQLFunction("ST_Intersects", + StandardBasicTypes.BOOLEAN)); + registerFunction("equals", new StandardSQLFunction("ST_Equals", + StandardBasicTypes.BOOLEAN)); + registerFunction("contains", new StandardSQLFunction("ST_Contains", + StandardBasicTypes.BOOLEAN)); + registerFunction("crosses", new StandardSQLFunction("ST_Crosses", + StandardBasicTypes.BOOLEAN)); + registerFunction("disjoint", new StandardSQLFunction("ST_Disjoint", + StandardBasicTypes.BOOLEAN)); + registerFunction("touches", new StandardSQLFunction("ST_Touches", + StandardBasicTypes.BOOLEAN)); + registerFunction("within", new StandardSQLFunction("ST_Within", + StandardBasicTypes.BOOLEAN)); +// NOT YET AVAILABLE IN GEODB +// registerFunction("relate", new StandardSQLFunction("relate", +// Hibernate.BOOLEAN)); + + // register the spatial analysis functions + registerFunction("distance", new StandardSQLFunction("ST_Distance", + StandardBasicTypes.DOUBLE)); + registerFunction("buffer", new StandardSQLFunction("ST_Buffer", + GeometryType.INSTANCE)); +// NOT YET AVAILABLE IN GEODB +// registerFunction("convexhull", new StandardSQLFunction("convexhull", +// new CustomType(GeoDBGeometryUserType.class, null))); +// registerFunction("difference", new StandardSQLFunction("difference", +// new CustomType(GeoDBGeometryUserType.class, null))); +// registerFunction("intersection", new StandardSQLFunction( +// "intersection", new CustomType(GeoDBGeometryUserType.class, null))); +// registerFunction("symdifference", +// new StandardSQLFunction("symdifference", new CustomType( +// GeoDBGeometryUserType.class, null))); +// registerFunction("geomunion", new StandardSQLFunction("geomunion", +// new CustomType(GeoDBGeometryUserType.class, null))); + + //register Spatial Aggregate funciton +// NOT YET AVAILABLE IN GEODB +// registerFunction("extent", new StandardSQLFunction("extent", +// new CustomType(GeoDBGeometryUserType.class, null))); + + registerFunction("dwithin", new StandardSQLFunction("ST_DWithin", + StandardBasicTypes.BOOLEAN)); + + } + + //TODO the getTypeName() override is necessary in the absence of HHH-6074 + + /** + * Get the name of the database type associated with the given + * {@link java.sql.Types} typecode with the given storage specification + * parameters. In the case of typecode == 3000, it returns this dialect's spatial type which is + * GEOMETRY. + * + * @param code The {@link java.sql.Types} typecode + * @param length The datatype length + * @param precision The datatype precision + * @param scale The datatype scale + * @return + * @throws org.hibernate.HibernateException + * + */ + @Override + public String getTypeName(int code, long length, int precision, int scale) throws HibernateException { + if (code == 3000) return "GEOMETRY"; + return super.getTypeName(code, length, precision, scale); + } + + @Override + public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) { + if (sqlTypeDescriptor instanceof GeometrySqlTypeDescriptor) { + return GeoDBGeometryTypeDescriptor.INSTANCE; + } + return super.remapSqlTypeDescriptor(sqlTypeDescriptor); + } + + /* (non-Javadoc) + * @see org.hibernatespatial.SpatialDialect#getSpatialAggregateSQL(java.lang.String, int) + */ + + public String getSpatialAggregateSQL(String columnName, int aggregation) { + switch (aggregation) { +// NOT YET AVAILABLE IN GEODB +// case SpatialAggregate.EXTENT: +// StringBuilder stbuf = new StringBuilder(); +// stbuf.append("extent(").append(columnName).append(")"); +// return stbuf.toString(); + default: + throw new IllegalArgumentException("Aggregations of type " + + aggregation + " are not supported by this dialect"); + } + } + + public String getDWithinSQL(String columnName) { + return "ST_DWithin(" + columnName + ",?,?)"; + } + + public String getHavingSridSQL(String columnName) { + return "( ST_srid(" + columnName + ") = ?)"; + } + + public String getIsEmptySQL(String columnName, boolean isEmpty) { + String emptyExpr = " ST_IsEmpty(" + columnName + ") "; + return isEmpty ? emptyExpr : "( NOT " + emptyExpr + ")"; + } + + /* (non-Javadoc) + * @see org.hibernatespatial.SpatialDialect#getSpatialFilterExpression(java.lang.String) + */ + public String getSpatialFilterExpression(String columnName) { + return "(" + columnName + " && ? ) "; + } + + /* (non-Javadoc) + * @see org.hibernatespatial.SpatialDialect#getSpatialRelateSQL(java.lang.String, int, boolean) + */ + + public String getSpatialRelateSQL(String columnName, int spatialRelation) { + switch (spatialRelation) { + case SpatialRelation.WITHIN: + return " ST_Within(" + columnName + ", ?)"; + case SpatialRelation.CONTAINS: + return " ST_Contains(" + columnName + ", ?)"; + case SpatialRelation.CROSSES: + return " ST_Crosses(" + columnName + ", ?)"; + case SpatialRelation.OVERLAPS: + return " ST_Overlaps(" + columnName + ", ?)"; + case SpatialRelation.DISJOINT: + return " ST_Disjoint(" + columnName + ", ?)"; + case SpatialRelation.INTERSECTS: + return " ST_Intersects(" + columnName + ", ?)"; + case SpatialRelation.TOUCHES: + return " ST_Touches(" + columnName + ", ?)"; + case SpatialRelation.EQUALS: + return " ST_Equals(" + columnName + ", ?)"; + default: + throw new IllegalArgumentException( + "Spatial relation is not known by this dialect"); + } + } + + /* (non-Javadoc) + * @see org.hibernatespatial.SpatialDialect#getDbGeometryTypeName() + */ + + public String getDbGeometryTypeName() { + return "GEOM"; + } + + /* (non-Javadoc) + * @see org.hibernatespatial.SpatialDialect#isTwoPhaseFiltering() + */ + + public boolean isTwoPhaseFiltering() { + return false; + } + + public boolean supportsFiltering() { + return false; + } + + public boolean supports(SpatialFunction function) { + if (function == SpatialFunction.difference) return false; + return (getFunctions().get(function.toString()) != null); + } + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBGeometryTypeDescriptor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBGeometryTypeDescriptor.java new file mode 100644 index 0000000000..c985cad3fe --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBGeometryTypeDescriptor.java @@ -0,0 +1,57 @@ +/* + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for spatial (geographic) data. + * + * Copyright © 2007-2012 Geovise BVBA, Geodan IT b.v. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.hibernate.spatial.dialect.h2geodb; + +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +import java.sql.Types; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 2/29/12 + */ +public class GeoDBGeometryTypeDescriptor implements SqlTypeDescriptor { + public static final GeoDBGeometryTypeDescriptor INSTANCE = new GeoDBGeometryTypeDescriptor(); + + @Override + public int getSqlType() { + return Types.ARRAY; + } + + @Override + public boolean canBeRemapped() { + return false; + } + + @Override + public ValueBinder getBinder(JavaTypeDescriptor javaTypeDescriptor) { + return (ValueBinder) new GeoDBValueBinder(); + } + + @Override + public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) { + return (ValueExtractor) new GeoDBValueExtractor(); + } +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBValueBinder.java new file mode 100644 index 0000000000..392e21f3ad --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBValueBinder.java @@ -0,0 +1,51 @@ +/* + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for spatial (geographic) data. + * + * Copyright © 2007-2012 Geovise BVBA, Geodan IT b.v. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.hibernate.spatial.dialect.h2geodb; + +import com.vividsolutions.jts.geom.Geometry; +import org.hibernate.spatial.Log; +import org.hibernate.spatial.LogFactory; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueBinder; + +import java.sql.Connection; + +/** + * @author Jan Boonen, Geodan IT b.v. + * @author Karel Maesen, Geovise BVBA + * creation-date: 2/29/12 + */ +public class GeoDBValueBinder extends AbstractJTSGeometryValueBinder { + + private static Log LOG = LogFactory.make(); + + @Override + protected Object toNative(Geometry jtsGeom, Connection connection) { + try { + return WKB.toWKB(jtsGeom); + } catch (Exception e) { + LOG.warn("Could not convert JTS Geometry to a database object."); + e.printStackTrace(); + return null; + } + } + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBValueExtractor.java new file mode 100644 index 0000000000..976d6fb64b --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBValueExtractor.java @@ -0,0 +1,144 @@ +/* + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for spatial (geographic) data. + * + * Copyright © 2007-2012 Geovise BVBA, Geodan IT b.v. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.hibernate.spatial.dialect.h2geodb; + +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKBConstants; +import org.hibernate.HibernateException; +import org.hibernate.spatial.Log; +import org.hibernate.spatial.LogFactory; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueExtractor; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.sql.Blob; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 2/29/12 + */ +public class GeoDBValueExtractor extends AbstractJTSGeometryValueExtractor { + + private static Log LOG = LogFactory.make(); + + @Override + public Geometry toJTS(Object object) { + if (object == null) + return null; + try { + if (object instanceof Blob) { + return WKB.fromWKB(toByteArray((Blob) object), getGeometryFactory()); + } else if (object instanceof byte[]) { + return geometryFromByteArray((byte[]) object); + } else if (object instanceof Envelope) { + return getGeometryFactory().toGeometry((Envelope) object); + } else { + throw new IllegalArgumentException( + "Can't convert database object of type " + + object.getClass().getCanonicalName()); + } + } catch (Exception e) { + LOG.warn("Could not convert database object to a JTS Geometry."); + throw new HibernateException(e); + } + } + + + /** + * Convert a WKB or EWKB byte array to a {@link Geometry}. To figure out + * whether the byte array is either a WKB or EWK the following checks are + * performed:
+ *

    + *
  1. If the first byte is not 0 or 1, the geometry must be an EWKB (with + * the first 32 bytes as a bounding box)
  2. + *
  3. Otherwise, the the byte array is parsed as a WKB
  4. + *
  5. When a parse error occurs it is assumed that the byte array is a EWKB + * (with the first byte accidentally a 0 or 1), and parsed as EWKB
  6. + *
+ * + * @param bytes + * @return + */ + private Geometry geometryFromByteArray(byte[] bytes) throws ParseException { + /* + * wkbXDR = 0, // Big Endian + * wkbNDR = 1 // Little Endian + */ + if (bytes[0] != WKBConstants.wkbNDR && bytes[0] != WKBConstants.wkbXDR) { + // process as EWKB + return WKB.fromEWKB(bytes, getGeometryFactory()); + } else { + // process as WKB + try { + return WKB.fromWKB(bytes, getGeometryFactory()); + } catch (RuntimeException e) { + // note: ParseException is wrapped in a RuntimeException in + // geodb.GeoDB + if (e.getCause() != null + && e.getCause() instanceof ParseException) { + // retry as EWKB, this should rarely happen, but may occur + // when the first byte of the EWKB bounding-box is '0'. + // this should not be considered as a error + LOG.debug( + "Caught parse exception while parsing byte array as WKB. Retrying as EWKB.", + e); + return WKB.fromEWKB(bytes, getGeometryFactory()); + } else { + // this is an other exception, simply re-throw + throw e; + } + } + } + } + + private byte[] toByteArray(Blob blob) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + + InputStream in = null; + try { + in = blob.getBinaryStream(); + int n = 0; + while ((n = in.read(buf)) >= 0) { + baos.write(buf, 0, n); + + } + } catch (Exception e) { + LOG.warn("Could not convert database BLOB object to binary stream.", e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + LOG.warn("Could not close binary stream."); + } + } + + return baos.toByteArray(); + } + + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/WKB.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/WKB.java new file mode 100644 index 0000000000..96cad337a9 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/WKB.java @@ -0,0 +1,66 @@ +/* + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for spatial (geographic) data. + * + * Copyright © 2007-2012 Geovise BVBA, Geodan IT b.v. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.hibernate.spatial.dialect.h2geodb; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKBReader; +import com.vividsolutions.jts.io.WKBWriter; + +/** + * A utility class to serialize from/to GeoDB WKB's. + *

+ *

Note: this utility makes it unnecessary to have a dependency on GeoDB. As long as GeoDB is + * not available in common maven repositories, such a dependency is to be avoided.

+ * + * @author Karel Maesen, Geovise BVBA + * creation-date: 2/29/12 + */ +class WKB { + + static Geometry fromWKB(byte[] bytes, GeometryFactory factory) throws ParseException { + WKBReader reader = new WKBReader(factory); + return reader.read(bytes); + } + + /** + * Reads a EWKB byte (which is just a WKB prepended with an envelope of 32 bytes. + * + * @param bytes + * @param factory + * @return + * @throws ParseException + */ + static Geometry fromEWKB(byte[] bytes, GeometryFactory factory) throws ParseException { + byte[] wkbBytes = new byte[bytes.length - 32]; + System.arraycopy(bytes, 32, wkbBytes, 0, bytes.length - 32); + return fromWKB(wkbBytes, factory); + } + + + static byte[] toWKB(Geometry jtsGeom) { + WKBWriter writer = new WKBWriter(2, true); + return writer.write(jtsGeom); + } +} + diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java index 32b1fd711f..8633786abc 100644 --- a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java @@ -1,6 +1,7 @@ package org.hibernate.spatial.testing; import org.hibernate.dialect.Dialect; +import org.hibernate.spatial.testing.dialects.h2geodb.GeoDBTestSupport; import org.hibernate.spatial.testing.dialects.mysql.MySQLTestSupport; import org.hibernate.spatial.testing.dialects.oracle.OracleSDOTestSupport; import org.hibernate.spatial.testing.dialects.postgis.PostgisTestSupport; @@ -48,9 +49,9 @@ public class TestSupportFactories { if ("org.hibernate.spatial.dialect.postgis.PostgisDialect".equals(canonicalName)) { return PostgisTestSupport.class; } -// if ("org.hibernate.spatial.geodb.GeoDBDialect".equals(canonicalName)) { -// return "org.hibernate.spatial.geodb.GeoDBSupport"; -// } + if ("org.hibernate.spatial.dialect.h2geodb.GeoDBDialect".equals(canonicalName)) { + return GeoDBTestSupport.class; + } if ("org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect".equals(canonicalName)) { return SQLServerTestSupport.class; } diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBDataSourceUtils.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBDataSourceUtils.java new file mode 100644 index 0000000000..45fd8475aa --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBDataSourceUtils.java @@ -0,0 +1,51 @@ +/** + * + */ +package org.hibernate.spatial.testing.dialects.h2geodb; + + +import org.hibernate.spatial.testing.DataSourceUtils; +import org.hibernate.spatial.testing.SQLExpressionTemplate; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Extension of the {@link DataSourceUtils} class which sets up an in-memory + * GeoDB database. The specified SQL file is used to generate a schema in the + * database. + * + * @author Jan Boonen, Geodan IT b.v. + */ +public class GeoDBDataSourceUtils extends DataSourceUtils { + + public GeoDBDataSourceUtils(String jdbcDriver, String jdbcUrl, String jdbcUser, String jdbcPass, + SQLExpressionTemplate sqlExpressionTemplate) + throws SQLException, IOException { + super(jdbcDriver, jdbcUrl, jdbcUser, jdbcPass, sqlExpressionTemplate); + Connection conn = this.getConnection(); + initGeoDB(conn); + } + + //initialise the GeoDB connection using Reflection + // so we do not introduce a compile-time dependency + private void initGeoDB(Connection conn) { + String errorMsg = "Problem initializing GeoDB."; + try { + Class geoDB = Thread.currentThread().getContextClassLoader().loadClass("geodb.GeoDB"); + Method m = geoDB.getDeclaredMethod("InitGeoDB", new Class[]{Connection.class}); + m.invoke(null, conn); + } catch (ClassNotFoundException e) { + throw new RuntimeException(errorMsg, e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(errorMsg, e); + } catch (InvocationTargetException e) { + throw new RuntimeException(errorMsg, e); + } catch (IllegalAccessException e) { + throw new RuntimeException(errorMsg, e); + } + } +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java new file mode 100644 index 0000000000..e61b3ab3c1 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java @@ -0,0 +1,411 @@ +/** + * + */ +package org.hibernate.spatial.testing.dialects.h2geodb; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; +import org.hibernate.spatial.dialect.h2geodb.GeoDBValueExtractor; +import org.hibernate.spatial.testing.AbstractExpectationsFactory; +import org.hibernate.spatial.testing.NativeSQLStatement; + + +/** + * A Factory class that generates expected {@link NativeSQLStatement}s for + * GeoDB. + * + * @Author Jan Boonen, Geodan IT b.v. + */ +public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { + + private final GeoDBValueExtractor decoder = new GeoDBValueExtractor(); + + public GeoDBExpectationsFactory(GeoDBDataSourceUtils dataSourceUtils) { + super(dataSourceUtils); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeAsBinaryStatement() + */ + + @Override + protected NativeSQLStatement createNativeAsBinaryStatement() { + return createNativeSQLStatement("select id, ST_AsEWKB(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeAsTextStatement() + */ + + @Override + protected NativeSQLStatement createNativeAsTextStatement() { + return createNativeSQLStatement("select id, ST_AsText(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeBoundaryStatement() + */ + + @Override + protected NativeSQLStatement createNativeBoundaryStatement() { + throw new UnsupportedOperationException( + "Method ST_Bounday() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeBufferStatement(java.lang.Double) + */ + + @Override + protected NativeSQLStatement createNativeBufferStatement(Double distance) { + return createNativeSQLStatement( + "select t.id, ST_Buffer(t.geom,?) from GEOMTEST t where ST_SRID(t.geom) = 4326", + new Object[]{distance}); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeContainsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeContainsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Contains(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Contains(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeConvexHullStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_ConvexHull() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeCrossesStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Crosses(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Crosses(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDifferenceStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_Difference() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDimensionSQL() + */ + + @Override + protected NativeSQLStatement createNativeDimensionSQL() { + throw new UnsupportedOperationException( + "Method ST_Dimension() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDisjointStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Disjoint(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Disjoint(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeTransformStatement(int epsg) { + throw new UnsupportedOperationException(); + } + + @Override + protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) { + return createNativeSQLStatement("select t.id, (ST_SRID(t.geom) = " + + srid + ") from GeomTest t where ST_SRID(t.geom) = " + srid); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDistanceStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, st_distance(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeEnvelopeStatement() + */ + + @Override + protected NativeSQLStatement createNativeEnvelopeStatement() { + return createNativeSQLStatement("select id, ST_Envelope(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeEqualsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Equals(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Equals(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeFilterStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeFilterStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Filter is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeGeomUnionStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_GeomUnion() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeGeometryTypeStatement() + */ + + @Override + protected NativeSQLStatement createNativeGeometryTypeStatement() { + return createNativeSQLStatement("select id, GeometryType(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIntersectionStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_Intersection() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIntersectsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Intersects(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Intersects(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIsEmptyStatement() + */ + + @Override + protected NativeSQLStatement createNativeIsEmptyStatement() { + return createNativeSQLStatement("select id, ST_IsEmpty(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeIsNotEmptyStatement() { + return createNativeSQLStatement("select id, not ST_IsEmpty(geom) from geomtest"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIsSimpleStatement() + */ + + @Override + protected NativeSQLStatement createNativeIsSimpleStatement() { + return createNativeSQLStatement("select id, ST_IsSimple(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeOverlapsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Overlaps(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Overlaps(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeRelateStatement(com.vividsolutions.jts.geom.Geometry, + * java.lang.String) + */ + + @Override + protected NativeSQLStatement createNativeRelateStatement(Geometry geom, + String matrix) { + throw new UnsupportedOperationException( + "Method ST_Relate() is not implemented in the current version of GeoDB."); + } + + @Override + protected NativeSQLStatement createNativeDwithinStatement(Point geom, + double distance) { + String sql = "select t.id, ST_DWithin(t.geom, ST_GeomFromText(?, 4326), " + + distance + + " ) from GEOMTEST t where st_dwithin(t.geom, ST_GeomFromText(?, 4326), " + + distance + ") = 'true' and ST_SRID(t.geom) = 4326"; + return createNativeSQLStatementAllWKTParams(sql, geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeSridStatement() + */ + + @Override + protected NativeSQLStatement createNativeSridStatement() { + return createNativeSQLStatement("select id, ST_SRID(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeSymDifferenceStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeSymDifferenceStatement( + Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_SymDifference() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeTouchesStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Touches(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Touches(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeWithinStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeWithinStatement( + Geometry testPolygon) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Within(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Within(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + testPolygon.toText()); + } + + /* + * (non-Javadoc) + * + * @see + * org.hibernatespatial.test.AbstractExpectationsFactory#decode(java.lang + * .Object) + */ + + @Override + protected Geometry decode(Object o) { + return decoder.toJTS(o); + } + +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpressionTemplate.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpressionTemplate.java new file mode 100644 index 0000000000..f6e5c14b3c --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpressionTemplate.java @@ -0,0 +1,28 @@ +package org.hibernate.spatial.testing.dialects.h2geodb; + +import org.hibernate.spatial.testing.SQLExpressionTemplate; +import org.hibernate.spatial.testing.TestDataElement; + +/** + * This is the template for insert SQL statements into the geomtest test table + * for GeoDB. + * + * @author Jan Boonen, Geodan IT b.v. + */ +public class GeoDBExpressionTemplate implements SQLExpressionTemplate { + + final String SQL_TEMPLATE = "insert into GEOMTEST values (%d, '%s', ST_GeomFromText('%s', %d))"; + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.SQLExpressionTemplate#toInsertSql(org. + * hibernatespatial.test.TestDataElement) + */ + public String toInsertSql(TestDataElement testDataElement) { + return String + .format(SQL_TEMPLATE, testDataElement.id, testDataElement.type, + testDataElement.wkt, testDataElement.srid); + } + +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBGeometryEquality.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBGeometryEquality.java new file mode 100644 index 0000000000..3b4c3cefd2 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBGeometryEquality.java @@ -0,0 +1,41 @@ +/** + * + */ +package org.hibernate.spatial.testing.dialects.h2geodb; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import org.hibernate.spatial.testing.GeometryEquality; + +/** + * Extends the test for {@link Geometry} equality, because GeoDB uses JTS + * Geometry objects, which cannot be cast to {@link org.hibernate.spatial.jts.mgeom.MGeometry} objects. + * + * @author Jan Boonen, Geodan IT b.v. + */ +public class GeoDBGeometryEquality extends GeometryEquality { + + @Override + public boolean test(Geometry geom1, Geometry geom2) { + if (geom1 != null && geom1.isEmpty()) + return geom2 == null || geom2.isEmpty(); + return super.test(geom1, geom2); + } + + @Override + protected boolean testSimpleGeometryEquality(Geometry geom1, Geometry geom2) { + return testVerticesEquality(geom1, geom2); + } + + private boolean testVerticesEquality(Geometry geom1, Geometry geom2) { + if (geom1.getNumPoints() != geom2.getNumPoints()) + return false; + for (int i = 0; i < geom1.getNumPoints(); i++) { + Coordinate cn1 = geom1.getCoordinates()[i]; + Coordinate cn2 = geom2.getCoordinates()[i]; + if (!cn1.equals2D(cn2)) + return false; + } + return true; + } +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java new file mode 100644 index 0000000000..7d378e47b1 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java @@ -0,0 +1,406 @@ +/** + * + */ +package org.hibernate.spatial.testing.dialects.h2geodb; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; +import org.hibernate.spatial.dialect.h2geodb.GeoDBValueExtractor; +import org.hibernate.spatial.testing.AbstractExpectationsFactory; +import org.hibernate.spatial.testing.NativeSQLStatement; + +/** + * A Factory class that generates expected {@link org.hibernate.spatial.testing.NativeSQLStatement}s for GeoDB + * version < 0.4. These versions don't support storage of the SRID value with + * the geometry. + * + * @author Jan Boonen, Geodan IT b.v. + */ +public class GeoDBNoSRIDExpectationsFactory extends AbstractExpectationsFactory { + + private final GeoDBValueExtractor decoder = new GeoDBValueExtractor(); + + public GeoDBNoSRIDExpectationsFactory(GeoDBDataSourceUtils dataSourceUtils) { + super(dataSourceUtils); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeAsBinaryStatement() + */ + + @Override + protected NativeSQLStatement createNativeAsBinaryStatement() { + return createNativeSQLStatement("select id, ST_AsEWKB(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeAsTextStatement() + */ + + @Override + protected NativeSQLStatement createNativeAsTextStatement() { + return createNativeSQLStatement("select id, ST_AsText(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeBoundaryStatement() + */ + + @Override + protected NativeSQLStatement createNativeBoundaryStatement() { + throw new UnsupportedOperationException( + "Method ST_Bounday() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeBufferStatement(java.lang.Double) + */ + + @Override + protected NativeSQLStatement createNativeBufferStatement(Double distance) { + return createNativeSQLStatement( + "select t.id, ST_Buffer(t.geom,?) from GEOMTEST t where ST_SRID(t.geom) = 4326", + new Object[]{distance}); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeContainsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeContainsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Contains(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Contains(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeConvexHullStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_ConvexHull() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeCrossesStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Crosses(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Crosses(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDifferenceStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_Difference() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDimensionSQL() + */ + + @Override + protected NativeSQLStatement createNativeDimensionSQL() { + throw new UnsupportedOperationException( + "Method ST_Dimension() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDisjointStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Disjoint(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Disjoint(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeTransformStatement(int epsg) { + throw new UnsupportedOperationException(); + } + + @Override + protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) { + return createNativeSQLStatement("select t.id, (st_srid(t.geom) = " + srid + ") from GeomTest t where ST_SRID(t.geom) = " + srid); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeDistanceStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, st_distance(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeEnvelopeStatement() + */ + + @Override + protected NativeSQLStatement createNativeEnvelopeStatement() { + return createNativeSQLStatement("select id, ST_Envelope(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeEqualsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Equals(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Equals(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeFilterStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeFilterStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_MBRIntersects() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeGeomUnionStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_GeomUnion() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeGeometryTypeStatement() + */ + + @Override + protected NativeSQLStatement createNativeGeometryTypeStatement() { + return createNativeSQLStatement("select id, GeometryType(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIntersectionStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_Intersection() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIntersectsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Intersects(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Intersects(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIsEmptyStatement() + */ + + @Override + protected NativeSQLStatement createNativeIsEmptyStatement() { + return createNativeSQLStatement("select id, ST_IsEmpty(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeIsNotEmptyStatement() { + return createNativeSQLStatement("select id, not ST_IsEmpty(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeIsSimpleStatement() + */ + + @Override + protected NativeSQLStatement createNativeIsSimpleStatement() { + return createNativeSQLStatement("select id, ST_IsSimple(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeOverlapsStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Overlaps(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Overlaps(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeRelateStatement(com.vividsolutions.jts.geom.Geometry, + * java.lang.String) + */ + + @Override + protected NativeSQLStatement createNativeRelateStatement(Geometry geom, + String matrix) { + throw new UnsupportedOperationException( + "Method ST_Relate() is not implemented in the current version of GeoDB."); + } + + @Override + protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) { + String sql = "select t.id, st_dwithin(t.geom, ST_GeomFromText(?, 4326), " + distance + " ) from GeomTest t where st_dwithin(t.geom, ST_GeomFromText(?, 4326), " + distance + ") = 'true' and ST_SRID(t.geom) = 4326"; + return createNativeSQLStatementAllWKTParams(sql, geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeSridStatement() + */ + + @Override + protected NativeSQLStatement createNativeSridStatement() { + return createNativeSQLStatement("select id, ST_SRID(geom) from GEOMTEST"); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeSymDifferenceStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeSymDifferenceStatement( + Geometry geom) { + throw new UnsupportedOperationException( + "Method ST_SymDifference() is not implemented in the current version of GeoDB."); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeTouchesStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Touches(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Touches(t.geom, ST_GeomFromText(?, 4326)) = 1", + geom.toText()); + } + + /* + * (non-Javadoc) + * + * @seeorg.hibernatespatial.test.AbstractExpectationsFactory# + * createNativeWithinStatement(com.vividsolutions.jts.geom.Geometry) + */ + + @Override + protected NativeSQLStatement createNativeWithinStatement( + Geometry testPolygon) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Within(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_Within(t.geom, ST_GeomFromText(?, 4326)) = 1 and ST_SRID(t.geom) = 4326", + testPolygon.toText()); + } + + /* + * (non-Javadoc) + * + * @see + * org.hibernatespatial.test.AbstractExpectationsFactory#decode(java.lang + * .Object) + */ + + @Override + protected Geometry decode(Object o) { + return decoder.toJTS(o); + } + +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBTestSupport.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBTestSupport.java new file mode 100644 index 0000000000..c9e0edf056 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBTestSupport.java @@ -0,0 +1,46 @@ +package org.hibernate.spatial.testing.dialects.h2geodb; + +import org.hibernate.cfg.Configuration; +import org.hibernate.spatial.testing.*; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +import java.io.IOException; +import java.sql.SQLException; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: Oct 2, 2010 + */ +public class GeoDBTestSupport extends TestSupport { + + + public DataSourceUtils createDataSourceUtil(Configuration configuration) { + super.createDataSourceUtil(configuration); + try { + return new GeoDBDataSourceUtils(driver(), url(), user(), passwd(), getSQLExpressionTemplate()); + } catch (SQLException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public TestData createTestData(BaseCoreFunctionalTestCase testcase) { + return TestData.fromFile("h2geodb/test-geodb-data-set.xml"); + } + + public GeometryEquality createGeometryEquality() { + return new GeoDBGeometryEquality(); + } + + public AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) { + return new GeoDBExpectationsFactory((GeoDBDataSourceUtils) dataSourceUtils); + } + + public SQLExpressionTemplate getSQLExpressionTemplate() { + return new GeoDBExpressionTemplate(); + } + + +} + diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/postgis/PostgisExpectationsFactory.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/postgis/PostgisExpectationsFactory.java index 749736d215..d983c592e7 100644 --- a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/postgis/PostgisExpectationsFactory.java +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/postgis/PostgisExpectationsFactory.java @@ -1,6 +1,4 @@ /* - * $Id:$ - * * This file is part of Hibernate Spatial, an extension to the * hibernate ORM solution for geographic data. * diff --git a/hibernate-spatial/src/test/resources/h2geodb/test-geodb-data-set.xml b/hibernate-spatial/src/test/resources/h2geodb/test-geodb-data-set.xml new file mode 100644 index 0000000000..32ae0dea16 --- /dev/null +++ b/hibernate-spatial/src/test/resources/h2geodb/test-geodb-data-set.xml @@ -0,0 +1,69 @@ + + + + + + 1 + POINT + POINT(10 5) + 4326 + + + 2 + POINT + POINT(52.25 2.53) + 4326 + + + 3 + POINT + POINT(51 12) + 4326 + + + 4 + POINT + POINT(10.0 2.0) + 4326 + + + + + 5 + LINESTRING + LINESTRING(10.0 5.0, 20.0 15.0) + 4326 + + + 6 + LINESTRING + LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0) + 4326 + + + + + 16 + POLYGON + POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) ) + 4326 + + + 18 + POLYGON + POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2)) + 4326 + + + 19 + POLYGON + POLYGON( (110 110, 110 120, 120 120, 120 110, 110 110) ) + 4326 + + +