From f7f39cb8d29a8315b0166221a5e6b856ee736794 Mon Sep 17 00:00:00 2001
From: Karel Maesen
Date: Mon, 22 Aug 2011 22:05:56 +0200
Subject: [PATCH] HHH-6510 Added Oracle SDOGeometry support.
---
hibernate-spatial/hibernate-spatial.gradle | 1 +
.../dialect/oracle/ConnectionFinder.java | 52 ++
.../oracle/DefaultConnectionFinder.java | 119 ++++
.../spatial/dialect/oracle/ElemInfo.java | 118 ++++
.../spatial/dialect/oracle/ElementType.java | 93 +++
.../dialect/oracle/GetDimensionFunction.java | 56 ++
.../oracle/GetGeometryTypeFunction.java | 62 ++
.../dialect/oracle/OracleJDBCTypeFactory.java | 213 +++++++
.../oracle/OracleSpatial10gDialect.java | 591 ++++++++++++++++++
.../spatial/dialect/oracle/Ordinates.java | 72 +++
.../dialect/oracle/SDOBooleanType.java | 78 +++
.../spatial/dialect/oracle/SDOGType.java | 105 ++++
.../spatial/dialect/oracle/SDOGeometry.java | 325 ++++++++++
.../oracle/SDOGeometryTypeDescriptor.java | 39 ++
.../oracle/SDOGeometryValueBinder.java | 357 +++++++++++
.../oracle/SDOGeometryValueExtractor.java | 522 ++++++++++++++++
.../dialect/oracle/SDOObjectMethod.java | 109 ++++
.../dialect/oracle/SDOObjectProperty.java | 104 +++
.../spatial/dialect/oracle/SDOPoint.java | 37 ++
.../dialect/oracle/SpatialAggregate.java | 91 +++
.../spatial/dialect/oracle/StructLoader.java | 20 +
.../spatial/dialect/oracle/TypeGeometry.java | 32 +
.../dialect/oracle/WrappedOGCFunction.java | 77 +++
.../criterion/OracleSpatialAggregate.java | 48 ++
.../criterion/OracleSpatialProjection.java | 86 +++
.../criterion/OracleSpatialProjections.java | 60 ++
.../criterion/OracleSpatialRestrictions.java | 204 ++++++
.../oracle/criterion/RelationshipMask.java | 45 ++
.../oracle/criterion/SDOParameterMap.java | 192 ++++++
.../SqlServer2008GeometryValueBinder.java | 8 +
.../SqlServer2008GeometryValueExtractor.java | 8 +
.../integration/SpatialIntegrator.java | 6 +
.../spatial/SpatialFunctionalTestCase.java | 1 -
.../spatial/TestSupportFactories.java | 6 +-
.../dialect/oracle/JDBCConnectionProxy.java | 234 +++++++
.../dialect/oracle/OracleSDOTestSupport.java | 37 ++
.../dialect/oracle/SDODataSourceUtils.java | 74 +++
.../SDOGeometryExpectationsFactory.java | 270 ++++++++
.../oracle/SDOGeometryExpressionTemplate.java | 39 ++
.../dialect/oracle/SDOTestDataElement.java | 47 ++
.../dialect/oracle/SDOTestDataReader.java | 50 ++
.../src/test/resources/hibernate.properties | 18 +-
....oracle.OracleSpatial10gDialect.properties | 27 +
.../test-sdo-geometry-data-set-2D.xml | 282 +++++++++
.../resources/test-sdo-geometry-data-set.xml | 401 ++++++++++++
45 files changed, 5407 insertions(+), 9 deletions(-)
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/DefaultConnectionFinder.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElemInfo.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElementType.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetDimensionFunction.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetGeometryTypeFunction.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/Ordinates.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOBooleanType.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGType.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectMethod.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectProperty.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOPoint.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SpatialAggregate.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/StructLoader.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/TypeGeometry.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/WrappedOGCFunction.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialAggregate.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjection.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjections.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialRestrictions.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/RelationshipMask.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/SDOParameterMap.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueBinder.java
create mode 100644 hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/JDBCConnectionProxy.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSDOTestSupport.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDODataSourceUtils.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpectationsFactory.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpressionTemplate.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataElement.java
create mode 100644 hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataReader.java
create mode 100644 hibernate-spatial/src/test/resources/org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect.properties
create mode 100644 hibernate-spatial/src/test/resources/test-sdo-geometry-data-set-2D.xml
create mode 100644 hibernate-spatial/src/test/resources/test-sdo-geometry-data-set.xml
diff --git a/hibernate-spatial/hibernate-spatial.gradle b/hibernate-spatial/hibernate-spatial.gradle
index 199f179f11..6f806d9382 100644
--- a/hibernate-spatial/hibernate-spatial.gradle
+++ b/hibernate-spatial/hibernate-spatial.gradle
@@ -20,6 +20,7 @@ dependencies {
testCompile( libraries.junit )
testCompile( project(':hibernate-testing') )
testCompile( [group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'])
+ testCompile([group: 'com.oracle.jdbc', name:'ojdbc6', version:'11.1.0.7.0'])
}
sourceSets {
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java
new file mode 100644
index 0000000000..46dd8ef80f
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java
@@ -0,0 +1,52 @@
+/**
+ * $Id: ConnectionFinder.java 268 2010-10-28 19:16:54Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.Connection;
+
+import org.hibernate.spatial.helper.FinderStrategy;
+
+/**
+ * The ConnectionFinder
returns an OracleConnection when given a
+ * Connection
object.
+ *
+ * The SDOGeometryType requires access to an OracleConnection
+ * object when converting a geometry to SDOGeometry
, prior to
+ * setting the geometry attribute in prepared statements. In some environments
+ * the prepared statements do not return an OracleConnection
but
+ * a wrapper. Implementations of this interface attempt to retrieve the
+ * OracleConnection
from the wrapper in such cases.
+ *
+ *
+ * @author Karel Maesen
+ */
+public interface ConnectionFinder extends
+ FinderStrategy {
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/DefaultConnectionFinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/DefaultConnectionFinder.java
new file mode 100644
index 0000000000..4f1807b508
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/DefaultConnectionFinder.java
@@ -0,0 +1,119 @@
+/**
+ * $Id: DefaultConnectionFinder.java 286 2011-02-04 21:16:23Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+
+import org.hibernate.HibernateException;
+import org.hibernate.spatial.helper.FinderException;
+
+/**
+ * Default ConnectionFinder
implementation.
+ *
+ * This implementation attempts to retrieve the OracleConnection
+ * by recursive reflection: it searches for methods that return
+ * Connection
objects, executes these methods and checks the
+ * result. If the result is of type OracleConnection
the object
+ * is returned, otherwise it recurses on it.
+ *
+ *
+ *
+ * @author Karel Maesen
+ */
+public class DefaultConnectionFinder implements ConnectionFinder {
+
+ private final static Class> oracleConnectionClass;
+
+ static {
+ try {
+ oracleConnectionClass = Class.forName( "oracle.jdbc.driver.OracleConnection" );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new HibernateException( "Can't find Oracle JDBC Driver on classpath." );
+ }
+ }
+
+ public Connection find(Connection con) throws FinderException {
+ if ( con == null ) {
+ return null;
+ }
+
+ if ( oracleConnectionClass.isInstance( con ) ) {
+ return con;
+ }
+ // try to find the Oracleconnection recursively
+ for ( Method method : con.getClass().getMethods() ) {
+ if ( method.getReturnType().isAssignableFrom(
+ java.sql.Connection.class
+ )
+ && method.getParameterTypes().length == 0 ) {
+
+ try {
+ method.setAccessible( true );
+ Connection oc = find( (Connection) ( method.invoke( con, new Object[] { } ) ) );
+ if ( oc == null ) {
+ throw new FinderException(
+ String.format(
+ "Tried retrieving OracleConnection from %s using method %s, but received null.",
+ con.getClass().getCanonicalName(),
+ method.getName()
+ )
+ );
+ }
+ return oc;
+ }
+ catch ( IllegalAccessException e ) {
+ throw new FinderException(
+ String.format(
+ "Illegal access on executing method %s when finding OracleConnection",
+ method.getName()
+ )
+ );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new FinderException(
+ String.format(
+ "Invocation exception on executing method %s when finding OracleConnection",
+ method.getName()
+ )
+ );
+ }
+
+
+ }
+ }
+ throw new FinderException(
+ "Couldn't get at the OracleSpatial Connection object from the PreparedStatement."
+ );
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElemInfo.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElemInfo.java
new file mode 100644
index 0000000000..82e6c8f61d
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElemInfo.java
@@ -0,0 +1,118 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.math.BigDecimal;
+import java.sql.Array;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 1, 2010
+ */
+class ElemInfo {
+
+ static final String TYPE_NAME = "MDSYS.SDO_ELEM_INFO_ARRAY";
+
+ private BigDecimal[] triplets;
+
+ public ElemInfo(int size) {
+ this.triplets = new BigDecimal[3 * size];
+ }
+
+ public ElemInfo(BigDecimal[] elem_info) {
+ this.triplets = elem_info;
+ }
+
+ public ElemInfo(Array array) {
+ if (array == null) {
+ this.triplets = new BigDecimal[]{};
+ return;
+ }
+ try {
+ triplets = (BigDecimal[]) array.getArray();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ public BigDecimal[] getElements() {
+ return this.triplets;
+ }
+
+ public int getSize() {
+ return this.triplets.length / 3;
+ }
+
+ public int getOrdinatesOffset(int i) {
+ return this.triplets[i * 3].intValue();
+ }
+
+ public void setOrdinatesOffset(int i, int offset) {
+ this.triplets[i * 3] = new BigDecimal(offset);
+ }
+
+ public ElementType getElementType(int i) {
+ int etype = this.triplets[i * 3 + 1].intValue();
+ int interp = this.triplets[i * 3 + 2].intValue();
+ ElementType et = ElementType.parseType(etype, interp);
+ return et;
+ }
+
+ public boolean isCompound(int i) {
+ return getElementType(i).isCompound();
+ }
+
+ public int getNumCompounds(int i) {
+ if (getElementType(i).isCompound()) {
+ return this.triplets[i * 3 + 2].intValue();
+ } else {
+ return 1;
+ }
+ }
+
+ public void setElement(int i, int ordinatesOffset, ElementType et,
+ int numCompounds) {
+ if (i > getSize()) {
+ throw new RuntimeException(
+ "Attempted to set more elements in ElemInfo Array than capacity.");
+ }
+ this.triplets[i * 3] = new BigDecimal(ordinatesOffset);
+ this.triplets[i * 3 + 1] = new BigDecimal(et.getEType());
+ this.triplets[i * 3 + 2] = et.isCompound() ? new BigDecimal(numCompounds) : new BigDecimal(et
+ .getInterpretation());
+ }
+
+ public String toString() {
+ return SDOGeometry.arrayToString(this.triplets);
+ }
+
+ public void addElement(BigDecimal[] element) {
+ BigDecimal[] newTriplets = new BigDecimal[this.triplets.length + element.length];
+ System.arraycopy(this.triplets, 0, newTriplets, 0,
+ this.triplets.length);
+ System.arraycopy(element, 0, newTriplets, this.triplets.length,
+ element.length);
+ this.triplets = newTriplets;
+ }
+
+ public void addElement(ElemInfo element) {
+ this.addElement(element.getElements());
+ }
+
+ public BigDecimal[] getElement(int i) {
+ BigDecimal[] ea = null;
+ if (this.getElementType(i).isCompound()) {
+ int numCompounds = this.getNumCompounds(i);
+ ea = new BigDecimal[numCompounds + 1];
+ } else {
+ ea = new BigDecimal[3];
+ }
+ System.arraycopy(this.triplets, 3 * i, ea, 0, ea.length);
+ return ea;
+ }
+
+// public ARRAY toOracleArray(Connection conn) throws SQLException {
+// ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor(
+// TYPE_NAME, conn);
+// return new ARRAY(arrayDescriptor, conn, this.triplets);
+// }
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElementType.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElementType.java
new file mode 100644
index 0000000000..c0eb74a4d9
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ElementType.java
@@ -0,0 +1,93 @@
+package org.hibernate.spatial.dialect.oracle;
+
+
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 1, 2010
+ */
+enum ElementType {
+ UNSUPPORTED(0, true), POINT(1, 1), ORIENTATION(1, 0), POINT_CLUSTER(1,
+ true), LINE_STRAITH_SEGMENTS(2, 1), LINE_ARC_SEGMENTS(2, 2), INTERIOR_RING_STRAIGHT_SEGMENTS(
+ 2003, 1), EXTERIOR_RING_STRAIGHT_SEGMENTS(1003, 1), INTERIOR_RING_ARC_SEGMENTS(
+ 2003, 2), EXTERIOR_RING_ARC_SEGMENTS(1003, 2), INTERIOR_RING_RECT(
+ 2003, 3), EXTERIOR_RING_RECT(1003, 3), INTERIOR_RING_CIRCLE(
+ 2003, 4), EXTERIOR_RING_CIRCLE(1003, 4), COMPOUND_LINE(4, true), COMPOUND_EXTERIOR_RING(
+ 1005, true), COMPOUND_INTERIOR_RING(2005, true);
+
+ private int etype;
+
+ private int interpretation = 2;
+
+ private boolean compound = false;
+
+ private ElementType(int etype, int interp) {
+ this.etype = etype;
+ this.interpretation = interp;
+
+ }
+
+ private ElementType(int etype, boolean compound) {
+ this.etype = etype;
+ this.compound = compound;
+ }
+
+ public int getEType() {
+ return this.etype;
+ }
+
+ public int getInterpretation() {
+ return this.interpretation;
+ }
+
+ /**
+ * @return true, if the SDO_INTERPRETATION value is the number of points
+ * or compounds in the element.
+ */
+ public boolean isCompound() {
+ return this.compound;
+ }
+
+ public boolean isLine() {
+ return (etype == 2 || etype == 4);
+ }
+
+ public boolean isInteriorRing() {
+ return (etype == 2003 || etype == 2005);
+ }
+
+ public boolean isExteriorRing() {
+ return (etype == 1003 || etype == 1005);
+ }
+
+ public boolean isStraightSegment() {
+ return (interpretation == 1);
+ }
+
+ public boolean isArcSegment() {
+ return (interpretation == 2);
+ }
+
+ public boolean isCircle() {
+ return (interpretation == 4);
+ }
+
+ public boolean isRect() {
+ return (interpretation == 3);
+ }
+
+ public static ElementType parseType(int etype, int interpretation) {
+ for (ElementType t : values()) {
+ if (t.etype == etype) {
+ if (t.isCompound()
+ || t.getInterpretation() == interpretation) {
+ return t;
+ }
+ }
+ }
+ throw new RuntimeException(
+ "Can't determine ElementType from etype:" + etype
+ + " and interp.:" + interpretation);
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetDimensionFunction.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetDimensionFunction.java
new file mode 100644
index 0000000000..e5ee0e3eb4
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetDimensionFunction.java
@@ -0,0 +1,56 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import java.util.List;
+
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.type.StandardBasicTypes;
+import org.hibernate.type.Type;
+
+/**
+ * Implements OGC function dimension for HQL.
+ */
+class GetDimensionFunction extends SDOObjectMethod {
+
+ GetDimensionFunction() {
+ super("Get_Dims", StandardBasicTypes.INTEGER);
+ }
+
+ public String render(Type firstArgumentType, final List args,
+ final SessionFactoryImplementor factory) {
+ StringBuffer buf = new StringBuffer();
+ if (args.isEmpty()) {
+ throw new IllegalArgumentException(
+ "First Argument in arglist must be object to "
+ + "which method is applied");
+ }
+
+ buf.append(args.get(0)).append(".").append(
+ getName()).append("()");
+ return buf.toString();
+ }
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetGeometryTypeFunction.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetGeometryTypeFunction.java
new file mode 100644
index 0000000000..43e1bc7e6e
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/GetGeometryTypeFunction.java
@@ -0,0 +1,62 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import java.util.List;
+
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.type.StandardBasicTypes;
+import org.hibernate.type.Type;
+
+/**
+ * HQL Implementation for the geometry ype function.
+ */
+class GetGeometryTypeFunction extends SDOObjectMethod {
+
+ GetGeometryTypeFunction() {
+ super("Get_GType", StandardBasicTypes.STRING);
+ }
+
+ public String render(Type firstArgumentType, final List args,
+ final SessionFactoryImplementor factory) {
+ StringBuffer buf = new StringBuffer();
+ if (args.isEmpty()) {
+ throw new IllegalArgumentException(
+ "First Argument in arglist must be object to which"
+ + " method is applied");
+ }
+
+ buf.append("CASE ").append(args.get(0)).append(".").append(
+ getName()).append("()");
+ buf.append(" WHEN 1 THEN 'POINT'").append(
+ " WHEN 2 THEN 'LINESTRING'").append(
+ " WHEN 3 THEN 'POLYGON'").append(
+ " WHEN 5 THEN 'MULTIPOINT'").append(
+ " WHEN 6 THEN 'MULTILINE'").append(
+ " WHEN 7 THEN 'MULTIPOLYGON'").append(" END");
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java
new file mode 100644
index 0000000000..0594d867de
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java
@@ -0,0 +1,213 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Struct;
+
+import org.hibernate.HibernateException;
+import org.hibernate.internal.util.ReflectHelper;
+import org.hibernate.spatial.helper.FinderException;
+
+/**
+ * Factory for Oracle JDBC extension types (ARRAY, STRUCT, ...).
+ *
+ * This factory creates the Oracle extension types using reflection in order to
+ * avoid creating compile-time dependencies on the proprietary Oracle driver.
+ *
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 3, 2010
+ */
+public class OracleJDBCTypeFactory implements SQLTypeFactory {
+
+ private static Class> datumClass;
+ private static Class> numberClass;
+ private static Class> arrayClass;
+ private static Class> structClass;
+ private static Class> arrayDescriptorClass;
+ private static Class> structDescriptorClass;
+ private static Method structDescriptorCreator;
+ private static Method arrayDescriptorCreator;
+ private static Constructor> numberConstructor;
+ private static Constructor> arrayConstructor;
+ private static Constructor> structConstructor;
+
+
+ static {
+ Object[] obj = findDescriptorCreator( "oracle.sql.StructDescriptor" );
+ structDescriptorClass = (Class>) obj[0];
+ structDescriptorCreator = (Method) obj[1];
+ obj = findDescriptorCreator( "oracle.sql.ArrayDescriptor" );
+ arrayDescriptorClass = (Class>) obj[0];
+ arrayDescriptorCreator = (Method) obj[1];
+ datumClass = findClass( "oracle.sql.Datum" );
+ numberClass = findClass( "oracle.sql.NUMBER" );
+ arrayClass = findClass( "oracle.sql.ARRAY" );
+ structClass = findClass( "oracle.sql.STRUCT" );
+
+ numberConstructor = findConstructor( numberClass, java.lang.Integer.TYPE );
+ arrayConstructor = findConstructor( arrayClass, arrayDescriptorClass, Connection.class, Object.class );
+ structConstructor = findConstructor( structClass, structDescriptorClass, Connection.class, Object[].class );
+ }
+
+ private static ConnectionFinder connectionFinder = new DefaultConnectionFinder();
+
+ private static Constructor> findConstructor(Class clazz, Class>... arguments) {
+ try {
+ return clazz.getConstructor( arguments );
+ }
+ catch ( NoSuchMethodException e ) {
+ throw new HibernateException( "Error finding constructor for oracle.sql type.", e );
+ }
+ }
+
+ private static Class> findClass(String name) {
+ try {
+ return ReflectHelper.classForName( name );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new HibernateException( "Class 'oracle.sql.Datum' not found on class path" );
+ }
+ }
+
+ private static Object[] findDescriptorCreator(String className) {
+ try {
+ Class clazz = ReflectHelper.classForName( className );
+ Method m = clazz.getMethod(
+ "createDescriptor",
+ String.class,
+ Connection.class
+ );
+ return new Object[] { clazz, m };
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new HibernateException( "Class 'StructDescriptor' not found on classpath" );
+ }
+ catch ( NoSuchMethodException e ) {
+ throw new HibernateException( "Class 'StructDescriptor' has no method 'createDescriptor(String,Connection)'" );
+ }
+ }
+
+ static ConnectionFinder getConnectionFinder() {
+ return connectionFinder;
+ }
+
+ static void setConnectionFinder(ConnectionFinder finder) {
+ connectionFinder = finder;
+ }
+
+
+ public Struct createStruct(SDOGeometry geom, Connection conn) throws SQLException {
+ Connection oracleConnection = null;
+ try {
+ oracleConnection = connectionFinder.find( conn );
+ }
+ catch ( FinderException e ) {
+ throw new HibernateException( "Problem finding Oracle Connection", e );
+ }
+
+ Object structDescriptor = createStructDescriptor( SDOGeometry.getTypeName(), oracleConnection );
+ Object[] attributes = createDatumArray( 5 );
+ attributes[0] = createNumber( geom.getGType().intValue() );
+ if ( geom.getSRID() > 0 ) {
+ attributes[1] = createNumber( geom.getSRID() );
+ }
+ else {
+ attributes[1] = null;
+ }
+ attributes[3] = createElemInfoArray( geom.getInfo(), oracleConnection );
+ attributes[4] = createOrdinatesArray( geom.getOrdinates(), oracleConnection );
+ return createStruct( structDescriptor, oracleConnection, attributes );
+ }
+
+ public Array createElemInfoArray(ElemInfo elemInfo, Connection conn) {
+ Object arrayDescriptor = createArrayDescriptor( ElemInfo.TYPE_NAME, conn );
+ return createArray( arrayDescriptor, conn, elemInfo.getElements() );
+ }
+
+
+ public Array createOrdinatesArray(Ordinates ordinates, Connection conn) throws SQLException {
+ Object arrayDescriptor = createArrayDescriptor( Ordinates.TYPE_NAME, conn );
+ return createArray( arrayDescriptor, conn, ordinates.getOrdinateArray() );
+
+ }
+
+
+ private Array createArray(Object descriptor, Connection conn, Object[] data) {
+ try {
+ return (Array) arrayConstructor.newInstance( descriptor, conn, data );
+ }
+ catch ( InstantiationException e ) {
+ throw new HibernateException( "Problem creating ARRAY.", e );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new HibernateException( "Problem creating ARRAY.", e );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new HibernateException( "Problem creating ARRAY.", e );
+ }
+ }
+
+ private Struct createStruct(Object descriptor, Connection conn, Object[] attributes) {
+ try {
+ return (Struct) structConstructor.newInstance( descriptor, conn, attributes );
+ }
+ catch ( InstantiationException e ) {
+ throw new HibernateException( "Problem creating STRUCT.", e );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new HibernateException( "Problem creating STRUCT.", e );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new HibernateException( "Problem creating STRUCT.", e );
+ }
+ }
+
+ private Object createStructDescriptor(String sqlType, Connection conn) {
+ try {
+ return structDescriptorCreator.invoke( null, sqlType, conn );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new HibernateException( "Error creating oracle STRUCT", e );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new HibernateException( "Error creating oracle STRUCT", e );
+ }
+ }
+
+ private Object createArrayDescriptor(String name, Connection conn) {
+ try {
+ return arrayDescriptorCreator.invoke( null, name, conn );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new HibernateException( "Error creating oracle ARRAY", e );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new HibernateException( "Error creating oracle ARRAY", e );
+ }
+ }
+
+ private Object[] createDatumArray(int size) {
+ return (Object[]) java.lang.reflect.Array.newInstance( datumClass, size );
+
+ }
+
+ private Object createNumber(int obj) {
+ try {
+ return numberConstructor.newInstance( obj );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new HibernateException( "Error creating oracle NUMBER", e );
+ }
+ catch ( InstantiationException e ) {
+ throw new HibernateException( "Error creating oracle NUMBER", e );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new HibernateException( "Error creating oracle NUMBER", e );
+ }
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java
new file mode 100644
index 0000000000..ca150d129f
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java
@@ -0,0 +1,591 @@
+/*
+ * $Id: OracleSpatial10gDialect.java 309 2011-05-18 14:04:23Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.QueryException;
+import org.hibernate.dialect.Oracle10gDialect;
+import org.hibernate.dialect.function.StandardSQLFunction;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.spatial.GeometryType;
+import org.hibernate.spatial.SpatialAnalysis;
+import org.hibernate.spatial.SpatialDialect;
+import org.hibernate.spatial.SpatialFunction;
+import org.hibernate.spatial.SpatialGeometrySqlTypeDescriptor;
+import org.hibernate.spatial.SpatialRelation;
+import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate;
+import org.hibernate.spatial.helper.PropertyFileReader;
+import org.hibernate.type.StandardBasicTypes;
+import org.hibernate.type.Type;
+import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+
+/**
+ * Spatial Dialect for Oracle10g databases.
+ *
+ * @author Karel Maesen
+ */
+public class OracleSpatial10gDialect extends Oracle10gDialect implements
+ SpatialDialect, Serializable {
+
+
+ /**
+ * Implementation of the OGC astext function for HQL.
+ */
+ private class AsTextFunction extends StandardSQLFunction {
+
+ private AsTextFunction() {
+ super("astext", StandardBasicTypes.STRING);
+ }
+
+ public String render(Type firstArgumentType, final List args,
+ final SessionFactoryImplementor factory) {
+
+ StringBuffer buf = new StringBuffer();
+ if (args.isEmpty()) {
+ throw new IllegalArgumentException(
+ "First Argument in arglist must be object "
+ + "to which method is applied");
+ }
+
+ buf.append("TO_CHAR(SDO_UTIL.TO_WKTGEOMETRY(").append(args.get(0))
+ .append("))");
+ return buf.toString();
+ }
+ }
+
+
+ /**
+ * HQL Spatial relation function.
+ */
+ private class SpatialRelateFunction extends StandardSQLFunction {
+ private final int relation;
+
+ private SpatialRelateFunction(final String name, final int relation) {
+ super(name, isOGCStrict() ? StandardBasicTypes.BOOLEAN
+ : new SDOBooleanType());
+ this.relation = relation;
+ }
+
+ public String render(Type firstArgumentType, final List args,
+ final SessionFactoryImplementor factory) {
+
+ if (args.size() < 2) {
+ throw new QueryException(
+ "Spatial relate functions require at least two arguments");
+ }
+
+ String srf;
+ return isOGCStrict() ?
+ getOGCSpatialRelateSQL((String) args.get(0),
+ (String) args.get(1), this.relation) :
+ getNativeSpatialRelateSQL((String) args.get(0),
+ (String) args.get(1), this.relation);
+ }
+
+ }
+
+ private class SpatialAnalysisFunction extends StandardSQLFunction {
+ private final int analysis;
+
+ private SpatialAnalysisFunction(String name, Type returnType,
+ int analysis) {
+ super(name, returnType);
+ this.analysis = analysis;
+ }
+
+ public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) {
+ return isOGCStrict() ? getSpatialAnalysisSQL(args, this.analysis,
+ false) : getNativeSpatialAnalysisSQL(args, analysis);
+ }
+
+ }
+
+ private class SpatialAggregationFunction extends StandardSQLFunction {
+
+ private final int aggregation;
+
+ private SpatialAggregationFunction(String name, Type returnType,
+ boolean isProjection, int aggregation) {
+ super(name, returnType);
+ this.aggregation = aggregation;
+ }
+
+ public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) {
+ return getNativeSpatialAggregateSQL((String) args.get(0),
+ this.aggregation);
+ }
+ }
+
+ public final static String SHORT_NAME = "oraclespatial";
+
+ private final static String CONNECTION_FINDER_PROPERTY = "CONNECTION-FINDER";
+
+ private final static Logger log = LoggerFactory
+ .getLogger(OracleSpatial10gDialect.class);
+
+ private String OGC_STRICT = "OGC_STRICT";
+
+ private Map features = new HashMap();
+
+ public OracleSpatial10gDialect() {
+ super();
+ // initialise features to default
+ features.put(OGC_STRICT, new Boolean(true));
+
+ // read configuration information from
+ // classpath
+ configure();
+
+ // register geometry type
+ registerColumnType(java.sql.Types.STRUCT, "MDSYS.SDO_GEOMETRY");
+
+ // registering OGC functions
+ // (spec_simplefeatures_sql_99-04.pdf)
+
+ // section 2.1.1.1
+ registerFunction("dimension", new GetDimensionFunction());
+ registerFunction("geometrytype", new GetGeometryTypeFunction());
+ registerFunction("srid", new SDOObjectProperty("SDO_SRID",
+ StandardBasicTypes.INTEGER));
+ registerFunction("envelope",
+ new StandardSQLFunction("SDO_GEOM.SDO_MBR", GeometryType.INSTANCE));
+ registerFunction("astext", new AsTextFunction());
+
+ registerFunction("asbinary", new StandardSQLFunction(
+ "SDO_UTIL.TO_WKBGEOMETRY", StandardBasicTypes.BINARY));
+ registerFunction("isempty", new WrappedOGCFunction("OGC_ISEMPTY",
+ StandardBasicTypes.BOOLEAN, new boolean[]{true}));
+ registerFunction("issimple", new WrappedOGCFunction("OGC_ISSIMPLE",
+ StandardBasicTypes.BOOLEAN, new boolean[]{true}));
+ registerFunction("boundary", new WrappedOGCFunction("OGC_BOUNDARY",
+ GeometryType.INSTANCE,
+ new boolean[]{true}));
+
+ // registerFunction("area", new AreaFunction());
+
+ // Register functions for spatial relation constructs
+ // section 2.1.1.2
+ registerFunction("overlaps", new SpatialRelateFunction("overlaps",
+ SpatialRelation.OVERLAPS));
+ registerFunction("intersects", new SpatialRelateFunction("intersects",
+ SpatialRelation.INTERSECTS));
+ registerFunction("contains", new SpatialRelateFunction("contains",
+ SpatialRelation.CONTAINS));
+ registerFunction("crosses", new SpatialRelateFunction("crosses",
+ SpatialRelation.CROSSES));
+ registerFunction("disjoint", new SpatialRelateFunction("disjoint",
+ SpatialRelation.DISJOINT));
+ registerFunction("equals", new SpatialRelateFunction("equals",
+ SpatialRelation.EQUALS));
+ registerFunction("touches", new SpatialRelateFunction("touches",
+ SpatialRelation.TOUCHES));
+ registerFunction("within", new SpatialRelateFunction("within",
+ SpatialRelation.WITHIN));
+ registerFunction("relate", new WrappedOGCFunction("OGC_RELATE",
+ StandardBasicTypes.BOOLEAN, new boolean[]{true, true, false}));
+
+ // Register spatial analysis functions.
+ // Section 2.1.1.3
+ registerFunction("distance", new SpatialAnalysisFunction("distance",
+ StandardBasicTypes.DOUBLE, SpatialAnalysis.DISTANCE));
+ registerFunction("buffer", new SpatialAnalysisFunction("buffer",
+ GeometryType.INSTANCE,
+ SpatialAnalysis.BUFFER));
+ registerFunction("convexhull", new SpatialAnalysisFunction(
+ "convexhull", GeometryType.INSTANCE,
+ SpatialAnalysis.CONVEXHULL));
+ registerFunction("difference", new SpatialAnalysisFunction(
+ "difference", GeometryType.INSTANCE,
+ SpatialAnalysis.DIFFERENCE));
+ registerFunction("intersection", new SpatialAnalysisFunction(
+ "intersection", GeometryType.INSTANCE,
+ SpatialAnalysis.INTERSECTION));
+ registerFunction("symdifference", new SpatialAnalysisFunction(
+ "symdifference", GeometryType.INSTANCE,
+ SpatialAnalysis.SYMDIFFERENCE));
+ registerFunction("geomunion", new SpatialAnalysisFunction("union",
+ GeometryType.INSTANCE,
+ SpatialAnalysis.UNION));
+ // we rename OGC union to geomunion because union is a reserved SQL
+ // keyword. (See also postgis documentation).
+
+ // portable spatial aggregate functions
+ registerFunction("extent", new SpatialAggregationFunction("extent",
+ GeometryType.INSTANCE, false,
+ OracleSpatialAggregate.EXTENT));
+
+ //other common functions
+ registerFunction("transform", new StandardSQLFunction("SDO_CS.TRANSFORM",
+ GeometryType.INSTANCE));
+
+ // Oracle specific Aggregate functions
+ registerFunction("centroid", new SpatialAggregationFunction("extent",
+ GeometryType.INSTANCE, false,
+ OracleSpatialAggregate.CENTROID));
+
+ registerFunction("concat_lines", new SpatialAggregationFunction(
+ "extent", GeometryType.INSTANCE, false,
+ OracleSpatialAggregate.CONCAT_LINES));
+
+ registerFunction("aggr_convexhull", new SpatialAggregationFunction(
+ "extent", GeometryType.INSTANCE, false,
+ OracleSpatialAggregate.CONVEXHULL));
+
+ registerFunction("aggr_union", new SpatialAggregationFunction("extent",
+ GeometryType.INSTANCE, false,
+ OracleSpatialAggregate.UNION));
+
+ registerFunction("lrs_concat", new SpatialAggregationFunction(
+ "lrsconcat", GeometryType.INSTANCE,
+ false, OracleSpatialAggregate.LRS_CONCAT));
+ }
+
+ @Override
+ public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
+ if ( sqlTypeDescriptor instanceof SpatialGeometrySqlTypeDescriptor ) {
+ return SDOGeometryTypeDescriptor.INSTANCE;
+ }
+ return super.remapSqlTypeDescriptor( sqlTypeDescriptor );
+ }
+
+ public String getNativeSpatialRelateSQL(String arg1, String arg2,
+ int spatialRelation) {
+ String mask = "";
+ boolean negate = false;
+ switch (spatialRelation) {
+ case SpatialRelation.INTERSECTS:
+ mask = "ANYINTERACT"; // OGC Compliance verified
+ break;
+ case SpatialRelation.CONTAINS:
+ mask = "CONTAINS+COVERS";
+ break;
+ case SpatialRelation.CROSSES:
+ throw new UnsupportedOperationException(
+ "Oracle Spatial does't have equivalent CROSSES relationship");
+ case SpatialRelation.DISJOINT:
+ mask = "ANYINTERACT";
+ negate = true;
+ break;
+ case SpatialRelation.EQUALS:
+ mask = "EQUAL";
+ break;
+ case SpatialRelation.OVERLAPS:
+ mask = "OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT";
+ break;
+ case SpatialRelation.TOUCHES:
+ mask = "TOUCH";
+ break;
+ case SpatialRelation.WITHIN:
+ mask = "INSIDE+COVEREDBY";
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "undefined SpatialRelation passed (" + spatialRelation
+ + ")");
+ }
+ StringBuffer buffer;
+ if (negate) {
+ buffer = new StringBuffer("CASE WHEN SDO_RELATE(");
+ } else {
+ buffer = new StringBuffer("SDO_RELATE(");
+ }
+
+
+ buffer.append(arg1);
+ buffer.append(",").append(arg2).append( ",'mask=" + mask + "') " );
+ if (negate) {
+ buffer.append(" = 'TRUE' THEN 'FALSE' ELSE 'TRUE' END");
+ }
+ return buffer.toString();
+ }
+
+ public String getOGCSpatialRelateSQL(String arg1, String arg2,
+ int spatialRelation) {
+
+ StringBuffer ogcFunction = new StringBuffer("MDSYS.");
+ switch (spatialRelation) {
+ case SpatialRelation.INTERSECTS:
+ ogcFunction.append("OGC_INTERSECTS");
+ break;
+ case SpatialRelation.CONTAINS:
+ ogcFunction.append("OGC_CONTAINS");
+ break;
+ case SpatialRelation.CROSSES:
+ ogcFunction.append("OGC_CROSS");
+ break;
+ case SpatialRelation.DISJOINT:
+ ogcFunction.append("OGC_DISJOINT");
+ break;
+ case SpatialRelation.EQUALS:
+ ogcFunction.append("OGC_EQUALS");
+ break;
+ case SpatialRelation.OVERLAPS:
+ ogcFunction.append("OGC_OVERLAP");
+ break;
+ case SpatialRelation.TOUCHES:
+ ogcFunction.append("OGC_TOUCH");
+ break;
+ case SpatialRelation.WITHIN:
+ ogcFunction.append("OGC_WITHIN");
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown SpatialRelation ("
+ + spatialRelation + ").");
+ }
+ ogcFunction.append("(").append("MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(")
+ .append(arg1).append("),").append(
+ "MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(").append(arg2)
+ .append(")").append(")");
+ return ogcFunction.toString();
+
+ }
+
+ public String getNativeSpatialAggregateSQL(String arg1, int aggregation) {
+
+ StringBuffer aggregateFunction = new StringBuffer();
+
+ SpatialAggregate sa = new SpatialAggregate(aggregation);
+
+ if (sa._aggregateSyntax == null) {
+ throw new IllegalArgumentException("Unknown Spatial Aggregation ("
+ + aggregation + ").");
+ }
+
+ aggregateFunction.append(sa._aggregateSyntax);
+
+ aggregateFunction.append("(");
+ if (sa.isAggregateType()) {
+ aggregateFunction.append("SDOAGGRTYPE(");
+ }
+ aggregateFunction.append(arg1);
+ // TODO tolerance must by configurable
+ if (sa.isAggregateType()) {
+ aggregateFunction.append(", ").append(.001).append(")");
+ }
+ aggregateFunction.append(")");
+
+ return aggregateFunction.toString();
+ }
+
+ private StringBuffer wrapInSTGeometry(String geomColumn, StringBuffer toAdd) {
+ return toAdd.append("MDSYS.ST_GEOMETRY(").append(geomColumn)
+ .append(")");
+ }
+
+ public String getSpatialFilterExpression(String columnName) {
+ StringBuffer buffer = new StringBuffer("SDO_FILTER(");
+ // String pureColumnName =
+ // columnName.substring(columnName.lastIndexOf(".")+1);
+ // buffer.append("\"" + pureColumnName.toUpperCase() + "\"");
+ buffer.append(columnName);
+ buffer.append(",?) = 'TRUE' ");
+ return buffer.toString();
+ }
+
+ public String getSpatialRelateSQL(String columnName, int spatialRelation) {
+
+ String sql = (isOGCStrict() ? (getOGCSpatialRelateSQL(columnName, "?",
+ spatialRelation) + " = 1") : (getNativeSpatialRelateSQL(
+ columnName, "?", spatialRelation) + "= 'TRUE'"));
+ sql += " and " + columnName + " is not null";
+ return sql;
+ }
+
+ public String getSpatialAnalysisSQL(List args, int spatialAnalysisFunction,
+ boolean useFilter) {
+ return isOGCStrict() ? getOGCSpatialAnalysisSQL(args,
+ spatialAnalysisFunction) : getNativeSpatialAnalysisSQL(args,
+ spatialAnalysisFunction);
+ }
+
+ public String getSpatialAggregateSQL(String columnName,
+ int spatialAggregateFunction) {
+ return getNativeSpatialAggregateSQL(
+ columnName,
+ spatialAggregateFunction
+ );
+ }
+
+ public String getDWithinSQL(String columnName) {
+ throw new UnsupportedOperationException("No DWithin in this dialect");
+ }
+
+ public String getHavingSridSQL(String columnName) {
+ return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName );
+ }
+
+ public String getIsEmptySQL(String columnName, boolean isEmpty) {
+ return String.format(
+ "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )",
+ columnName,
+ isEmpty ? 1 : 0
+ );
+ }
+
+ private String getOGCSpatialAnalysisSQL(List args,
+ int spatialAnalysisFunction) {
+ boolean[] geomArgs;
+ StringBuffer ogcFunction = new StringBuffer("MDSYS.");
+ boolean isGeomReturn = true;
+ switch (spatialAnalysisFunction) {
+ case SpatialAnalysis.BUFFER:
+ ogcFunction.append("OGC_BUFFER");
+ geomArgs = new boolean[]{true, false};
+ break;
+ case SpatialAnalysis.CONVEXHULL:
+ ogcFunction.append("OGC_CONVEXHULL");
+ geomArgs = new boolean[]{true};
+ break;
+ case SpatialAnalysis.DIFFERENCE:
+ ogcFunction.append("OGC_DIFFERENCE");
+ geomArgs = new boolean[]{true, true};
+ break;
+ case SpatialAnalysis.DISTANCE:
+ ogcFunction.append("OGC_DISTANCE");
+ geomArgs = new boolean[]{true, true};
+ isGeomReturn = false;
+ break;
+ case SpatialAnalysis.INTERSECTION:
+ ogcFunction.append("OGC_INTERSECTION");
+ geomArgs = new boolean[]{true, true};
+ break;
+ case SpatialAnalysis.SYMDIFFERENCE:
+ ogcFunction.append("OGC_SYMMETRICDIFFERENCE");
+ geomArgs = new boolean[]{true, true};
+ break;
+ case SpatialAnalysis.UNION:
+ ogcFunction.append("OGC_UNION");
+ geomArgs = new boolean[]{true, true};
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unknown SpatialAnalysisFunction ("
+ + spatialAnalysisFunction + ").");
+ }
+
+ if (args.size() < geomArgs.length)
+ throw new QueryException(
+ "Insufficient arguments for spatial analysis function (function type: "
+ + spatialAnalysisFunction + ").");
+
+ ogcFunction.append("(");
+ for (int i = 0; i < geomArgs.length; i++) {
+ if (i > 0)
+ ogcFunction.append(",");
+ if (geomArgs[i])
+ wrapInSTGeometry((String) args.get(i), ogcFunction);
+ else
+ ogcFunction.append(args.get(i));
+ }
+ ogcFunction.append(")");
+ if (isGeomReturn)
+ ogcFunction.append(".geom");
+ return ogcFunction.toString();
+ }
+
+ private String getNativeSpatialAnalysisSQL(List args, int spatialAnalysis) {
+ return getOGCSpatialAnalysisSQL( args, spatialAnalysis );
+ }
+
+ boolean isOGCStrict() {
+ return ((Boolean) this.features.get(OGC_STRICT)).booleanValue();
+ }
+
+
+
+ private void configure() {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ String propfileLoc = getClass().getCanonicalName() + ".properties";
+ URL propfile = loader.getResource(propfileLoc);
+ if (propfile != null) {
+ InputStream is = null;
+ log.info("properties file found: " + propfile);
+ try {
+ loader.getResource(getClass().getCanonicalName());
+ is = propfile.openStream();
+ PropertyFileReader reader = new PropertyFileReader(is);
+ Properties props = reader.getProperties();
+
+ // checking for connectionfinder
+ String ccn = props.getProperty(CONNECTION_FINDER_PROPERTY);
+ if (ccn != null) {
+ try {
+ Class clazz = Thread.currentThread()
+ .getContextClassLoader().loadClass(ccn);
+ ConnectionFinder cf = (ConnectionFinder) clazz
+ .newInstance();
+ OracleJDBCTypeFactory.setConnectionFinder(cf);
+ log.info("Setting ConnectionFinder to " + ccn);
+ } catch (ClassNotFoundException e) {
+ log.warn("Tried to set ConnectionFinder to " + ccn
+ + ", but class not found.");
+ } catch (InstantiationException e) {
+ log.warn("Tried to set ConnectionFinder to " + ccn
+ + ", but couldn't instantiate.");
+ } catch (IllegalAccessException e) {
+ log
+ .warn("Tried to set ConnectionFinder to "
+ + ccn
+ + ", but got IllegalAcessException on instantiation.");
+ }
+ }
+
+ } catch (IOException e) {
+ log.warn("Problem reading properties file " + e);
+ } finally {
+ try {
+ is.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+
+ public boolean isTwoPhaseFiltering() {
+ return false;
+ }
+
+ public boolean supportsFiltering() {
+ return true;
+ }
+
+ public boolean supports(SpatialFunction function) {
+ return (getFunctions().get(function.toString()) != null);
+ }
+
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/Ordinates.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/Ordinates.java
new file mode 100644
index 0000000000..b2276a3e50
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/Ordinates.java
@@ -0,0 +1,72 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.Array;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 1, 2010
+ */
+class Ordinates {
+
+ static final String TYPE_NAME = "MDSYS.SDO_ORDINATE_ARRAY";
+
+ private Double[] ordinates;
+
+ public Ordinates(Double[] ordinates) {
+ this.ordinates = ordinates;
+ }
+
+ public Ordinates(Array array) {
+ if (array == null) {
+ this.ordinates = new Double[]{};
+ return;
+ }
+ try {
+ Number[] ords = (Number[]) array.getArray();
+ this.ordinates = new Double[ords.length];
+ for (int i = 0; i < ords.length; i++) {
+ this.ordinates[i] = ords[i] != null ? ords[i].doubleValue()
+ : Double.NaN;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Double[] getOrdinateArray() {
+ return this.ordinates;
+ }
+
+ public Double[] getOrdinatesArray(int startPosition, int endPosition) {
+ Double[] a = new Double[endPosition - startPosition];
+ System.arraycopy(this.ordinates, startPosition - 1, a, 0, a.length);
+ return a;
+ }
+
+ public Double[] getOrdinatesArray(int startPosition) {
+ Double[] a = new Double[this.ordinates.length - (startPosition - 1)];
+ System.arraycopy(this.ordinates, startPosition - 1, a, 0, a.length);
+ return a;
+ }
+
+ public String toString() {
+ return SDOGeometry.arrayToString(this.ordinates);
+ }
+
+ public void addOrdinates(Double[] ordinatesToAdd) {
+ Double[] newOrdinates = new Double[this.ordinates.length
+ + ordinatesToAdd.length];
+ System.arraycopy(this.ordinates, 0, newOrdinates, 0,
+ this.ordinates.length);
+ System.arraycopy(ordinatesToAdd, 0, newOrdinates,
+ this.ordinates.length, ordinatesToAdd.length);
+ this.ordinates = newOrdinates;
+ }
+
+// public ARRAY toOracleArray(Connection conn) throws SQLException {
+// ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor(
+// TYPE_NAME, conn);
+// return new ARRAY(arrayDescriptor, conn, this.ordinates);
+// }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOBooleanType.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOBooleanType.java
new file mode 100644
index 0000000000..979fd5990b
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOBooleanType.java
@@ -0,0 +1,78 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.type.BooleanType;
+
+class SDOBooleanType extends BooleanType {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ *
+ * This type's name is sdo_boolean
+ */
+ public String getName() {
+ return "sdo_boolean";
+ }
+
+ public Object get(ResultSet rs, String name) throws SQLException {
+ String value = rs.getString(name);
+ if (rs.wasNull()) {
+ return getDefaultValue();
+ } else if ("TRUE".equalsIgnoreCase(value)) {
+ return Boolean.TRUE;
+ } else {
+ return Boolean.FALSE;
+ }
+ }
+
+ public void set(PreparedStatement st, Boolean value, int index)
+ throws SQLException {
+
+ if (value == null) {
+ st.setNull(index, Types.VARCHAR);
+ } else {
+ boolean bool = value.booleanValue();
+ st.setString(index, bool ? "TRUE" : "FALSE");
+ }
+ }
+
+ public String objectToSQLString(Boolean value, Dialect dialect) {
+ return value.booleanValue() ? "'TRUE'" : "'FALSE'";
+ }
+
+// public int sqlType() {
+// return Types.VARCHAR;
+// }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGType.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGType.java
new file mode 100644
index 0000000000..f6a2c8c18d
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGType.java
@@ -0,0 +1,105 @@
+package org.hibernate.spatial.dialect.oracle;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jun 30, 2010
+ */
+class SDOGType {
+
+ private int dimension = 2;
+
+ private int lrsDimension = 0;
+
+ private TypeGeometry typeGeometry = TypeGeometry.UNKNOWN_GEOMETRY;
+
+ public SDOGType(int dimension, int lrsDimension,
+ TypeGeometry typeGeometry) {
+ setDimension(dimension);
+ setLrsDimension(lrsDimension);
+ setTypeGeometry(typeGeometry);
+ }
+
+ public int getDimension() {
+ return dimension;
+ }
+
+ public void setDimension(int dimension) {
+ if (dimension < 2 || dimension > 4) {
+ throw new IllegalArgumentException(
+ "Dimension can only be 2,3 or 4.");
+ }
+ this.dimension = dimension;
+ }
+
+ public TypeGeometry getTypeGeometry() {
+ return typeGeometry;
+ }
+
+ public void setTypeGeometry(TypeGeometry typeGeometry) {
+
+ this.typeGeometry = typeGeometry;
+ }
+
+ public int getLRSDimension() {
+ if (this.lrsDimension > 0) {
+ return this.lrsDimension;
+ } else if (this.lrsDimension == 0 && this.dimension == 4) {
+ return 4;
+ }
+ return 0;
+ }
+
+ public int getZDimension() {
+ if (this.dimension > 2) {
+ if (!isLRSGeometry()) {
+ return this.dimension;
+ } else {
+ return (getLRSDimension() < this.dimension ? 4 : 3);
+ }
+ }
+ return 0;
+ }
+
+ public boolean isLRSGeometry() {
+ return (this.lrsDimension > 0 || (this.lrsDimension == 0 && this.dimension == 4));
+ }
+
+ public void setLrsDimension(int lrsDimension) {
+ if (lrsDimension != 0 && lrsDimension > this.dimension) {
+ throw new IllegalArgumentException(
+ "lrsDimension must be 0 or lower or equal to dimenstion.");
+ }
+ this.lrsDimension = lrsDimension;
+ }
+
+ public int intValue() {
+ int v = this.dimension * 1000;
+ v += lrsDimension * 100;
+ v += typeGeometry.intValue();
+ return v;
+ }
+
+ public static SDOGType parse(int v) {
+ int dim = v / 1000;
+ v -= dim * 1000;
+ int lrsDim = v / 100;
+ v -= lrsDim * 100;
+ TypeGeometry typeGeometry = TypeGeometry.parse(v);
+ return new SDOGType(dim, lrsDim, typeGeometry);
+ }
+
+ public static SDOGType parse(Object datum) {
+
+ try {
+ int v = ((Number) datum).intValue();
+ return parse(v);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public String toString() {
+ return Integer.toString(this.intValue());
+ }
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java
new file mode 100644
index 0000000000..2dc517cc9e
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java
@@ -0,0 +1,325 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Struct;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hibernate.spatial.helper.FinderException;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jun 30, 2010
+ */
+
+class SDOGeometry {
+
+ private final static SQLTypeFactory TYPE_FACTORY = new OracleJDBCTypeFactory();
+ private static final String SQL_TYPE_NAME = "MDSYS.SDO_GEOMETRY";
+
+ private SDOGType gtype;
+
+ private int srid;
+
+ private SDOPoint point;
+
+ private ElemInfo info;
+
+ private Ordinates ordinates;
+
+
+ public SDOGeometry() {
+
+ }
+
+ public static String getTypeName() {
+ return SQL_TYPE_NAME;
+ }
+
+ static String arrayToString(Object array) {
+ if (array == null || java.lang.reflect.Array.getLength(array) == 0) {
+ return "()";
+ }
+ int length = java.lang.reflect.Array.getLength(array);
+ StringBuilder stb = new StringBuilder();
+ stb.append("(").append(java.lang.reflect.Array.get(array, 0));
+ for (int i = 1; i < length; i++) {
+ stb.append(",").append(java.lang.reflect.Array.get(array, i));
+ }
+ stb.append(")");
+ return stb.toString();
+ }
+
+
+ /**
+ * This joins an array of SDO_GEOMETRIES to a SDOGeometry of type
+ * COLLECTION
+ *
+ * @param SDOElements
+ * @return
+ */
+ public static SDOGeometry join(SDOGeometry[] SDOElements) {
+ SDOGeometry SDOCollection = new SDOGeometry();
+ if (SDOElements == null || SDOElements.length == 0) {
+ SDOCollection.setGType(new SDOGType(2, 0,
+ TypeGeometry.COLLECTION));
+ } else {
+ SDOGeometry firstElement = SDOElements[0];
+ int dim = firstElement.getGType().getDimension();
+ int lrsDim = firstElement.getGType().getLRSDimension();
+ SDOCollection.setGType(new SDOGType(dim, lrsDim,
+ TypeGeometry.COLLECTION));
+ int ordinatesOffset = 1;
+ for (int i = 0; i < SDOElements.length; i++) {
+ ElemInfo element = SDOElements[i].getInfo();
+ Double[] ordinates = SDOElements[i].getOrdinates()
+ .getOrdinateArray();
+ if (element != null && element.getSize() > 0) {
+ int shift = ordinatesOffset
+ - element.getOrdinatesOffset(0);
+ shiftOrdinateOffset(element, shift);
+ SDOCollection.addElement(element);
+ SDOCollection.addOrdinates(ordinates);
+ ordinatesOffset += ordinates.length;
+ }
+ }
+ }
+ return SDOCollection;
+ }
+
+ public ElemInfo getInfo() {
+ return info;
+ }
+
+ public void setInfo(ElemInfo info) {
+ this.info = info;
+ }
+
+ public SDOGType getGType() {
+ return gtype;
+ }
+
+ public void setGType(SDOGType gtype) {
+ this.gtype = gtype;
+ }
+
+ public Ordinates getOrdinates() {
+ return ordinates;
+ }
+
+ public void setOrdinates(Ordinates ordinates) {
+ this.ordinates = ordinates;
+ }
+
+ public SDOPoint getPoint() {
+ return point;
+ }
+
+ public void setPoint(SDOPoint point) {
+ this.point = point;
+ }
+
+ public int getSRID() {
+ return srid;
+ }
+
+ public void setSRID(int srid) {
+ this.srid = srid;
+ }
+
+ public static SDOGeometry load(Struct struct) {
+
+ Object[] data;
+ try {
+ data = struct.getAttributes();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(SDOGType.parse(data[0]));
+ geom.setSRID(data[1]);
+ if (data[2] != null) {
+ geom.setPoint(new SDOPoint((Struct) data[2]));
+ }
+ geom.setInfo(new ElemInfo((Array) data[3]));
+ geom.setOrdinates(new Ordinates((Array) data[4]));
+
+ return geom;
+ }
+
+ public static Struct store(SDOGeometry geom, Connection conn)
+ throws SQLException, FinderException {
+ return TYPE_FACTORY.createStruct(geom, conn);
+ }
+
+
+ private void setSRID(Object datum) {
+ if (datum == null) {
+ this.srid = 0;
+ return;
+ }
+ try {
+ this.srid = new Integer(((Number) datum).intValue());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean isLRSGeometry() {
+ return gtype.isLRSGeometry();
+ }
+
+ public int getDimension() {
+ return gtype.getDimension();
+ }
+
+ public int getLRSDimension() {
+ return gtype.getLRSDimension();
+ }
+
+ public int getZDimension() {
+ return gtype.getZDimension();
+ }
+
+ /**
+ * Gets the number of elements or compound elements.
+ *
+ * Subelements of a compound element are not counted.
+ *
+ * @return the number of elements
+ */
+ public int getNumElements() {
+ int cnt = 0;
+ int i = 0;
+ while (i < info.getSize()) {
+ if (info.getElementType(i).isCompound()) {
+ int numCompounds = info.getNumCompounds(i);
+ i += 1 + numCompounds;
+ } else {
+ i++;
+ }
+ cnt++;
+ }
+ return cnt;
+ }
+
+ public String toString() {
+ StringBuilder stb = new StringBuilder();
+ stb.append("(").append(gtype).append(",").append(srid).append(",")
+ .append(point).append(",").append(info).append(",").append(
+ ordinates).append(")");
+ return stb.toString();
+ }
+
+ public void addOrdinates(Double[] newOrdinates) {
+ if (this.ordinates == null) {
+ this.ordinates = new Ordinates(newOrdinates);
+ } else {
+ this.ordinates.addOrdinates(newOrdinates);
+ }
+ }
+
+ public void addElement(ElemInfo element) {
+ if (this.info == null) {
+ this.info = element;
+ } else {
+ this.info.addElement(element);
+ }
+ }
+
+ /**
+ * If this SDOGeometry is a COLLECTION, this method returns an array of
+ * the SDO_GEOMETRIES that make up the collection. If not a Collection,
+ * an array containing this SDOGeometry is returned.
+ *
+ * @return collection elements as individual SDO_GEOMETRIES
+ */
+ public SDOGeometry[] getElementGeometries() {
+ if (getGType().getTypeGeometry() == TypeGeometry.COLLECTION) {
+ List elements = new ArrayList();
+ int i = 0;
+ while (i < this.getNumElements()) {
+ ElementType et = this.getInfo().getElementType(i);
+ int next = i + 1;
+ // if the element is an exterior ring, or a compound
+ // element, then this geometry spans multiple elements.
+ if (et.isExteriorRing()) { // then next element is the
+ // first non-interior ring
+ while (next < this.getNumElements()) {
+ if (!this.getInfo().getElementType(next)
+ .isInteriorRing()) {
+ break;
+ }
+ next++;
+ }
+ } else if (et.isCompound()) {
+ next = i + this.getInfo().getNumCompounds(i) + 1;
+ }
+ SDOGeometry elemGeom = new SDOGeometry();
+ SDOGType elemGtype = deriveGTYPE(this.getInfo()
+ .getElementType(i), this);
+ elemGeom.setGType(elemGtype);
+ elemGeom.setSRID(this.getSRID());
+ ElemInfo elemInfo = new ElemInfo(this.getInfo()
+ .getElement(i));
+ shiftOrdinateOffset(elemInfo, -elemInfo
+ .getOrdinatesOffset(0) + 1);
+ elemGeom.setInfo(elemInfo);
+ int startPosition = this.getInfo().getOrdinatesOffset(i);
+ Ordinates elemOrdinates = null;
+ if (next < this.getNumElements()) {
+ int endPosition = this.getInfo().getOrdinatesOffset(
+ next);
+ elemOrdinates = new Ordinates(this.getOrdinates()
+ .getOrdinatesArray(startPosition, endPosition));
+ } else {
+ elemOrdinates = new Ordinates(this.getOrdinates()
+ .getOrdinatesArray(startPosition));
+ }
+ elemGeom.setOrdinates(elemOrdinates);
+ elements.add(elemGeom);
+ i = next;
+ }
+ return elements.toArray(new SDOGeometry[elements.size()]);
+ } else {
+ return new SDOGeometry[]{this};
+ }
+ }
+
+ private static void shiftOrdinateOffset(ElemInfo elemInfo, int offset) {
+ for (int i = 0; i < elemInfo.getSize(); i++) {
+ int newOffset = elemInfo.getOrdinatesOffset(i) + offset;
+ elemInfo.setOrdinatesOffset(i, newOffset);
+ }
+ }
+
+ private static SDOGType deriveGTYPE(ElementType elementType,
+ SDOGeometry origGeom) {
+ switch (elementType) {
+ case POINT:
+ case ORIENTATION:
+ return new SDOGType(origGeom.getDimension(), origGeom
+ .getLRSDimension(), TypeGeometry.POINT);
+ case POINT_CLUSTER:
+ return new SDOGType(origGeom.getDimension(), origGeom
+ .getLRSDimension(), TypeGeometry.MULTIPOINT);
+ case LINE_ARC_SEGMENTS:
+ case LINE_STRAITH_SEGMENTS:
+ case COMPOUND_LINE:
+ return new SDOGType(origGeom.getDimension(), origGeom
+ .getLRSDimension(), TypeGeometry.LINE);
+ case COMPOUND_EXTERIOR_RING:
+ case EXTERIOR_RING_ARC_SEGMENTS:
+ case EXTERIOR_RING_CIRCLE:
+ case EXTERIOR_RING_RECT:
+ case EXTERIOR_RING_STRAIGHT_SEGMENTS:
+ return new SDOGType(origGeom.getDimension(), origGeom
+ .getLRSDimension(), TypeGeometry.POLYGON);
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java
new file mode 100644
index 0000000000..539d3bc327
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java
@@ -0,0 +1,39 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.Types;
+
+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;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: 8/22/11
+ */
+public class SDOGeometryTypeDescriptor implements SqlTypeDescriptor {
+
+ public static SDOGeometryTypeDescriptor INSTANCE = new SDOGeometryTypeDescriptor();
+
+ @Override
+ public int getSqlType() {
+ return Types.STRUCT;
+ }
+
+ @Override
+ public boolean canBeRemapped() {
+ return false;
+ }
+
+ @Override
+ public ValueBinder getBinder(final JavaTypeDescriptor javaTypeDescriptor) {
+ return (ValueBinder) new SDOGeometryValueBinder();
+ }
+
+ @Override
+ public ValueExtractor getExtractor(final JavaTypeDescriptor javaTypeDescriptor) {
+ return (ValueExtractor) new SDOGeometryValueExtractor();
+ }
+
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java
new file mode 100644
index 0000000000..b9f99c4c7f
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java
@@ -0,0 +1,357 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import com.vividsolutions.jts.algorithm.CGAlgorithms;
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.GeometryCollection;
+import com.vividsolutions.jts.geom.LineString;
+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 org.hibernate.HibernateException;
+import org.hibernate.spatial.HBSpatialExtension;
+import org.hibernate.spatial.helper.FinderException;
+import org.hibernate.spatial.mgeom.MCoordinate;
+import org.hibernate.spatial.mgeom.MGeometryFactory;
+import org.hibernate.type.descriptor.ValueBinder;
+import org.hibernate.type.descriptor.WrapperOptions;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: 8/22/11
+ */
+public class SDOGeometryValueBinder implements ValueBinder {
+
+ @Override
+ public void bind(PreparedStatement st, Geometry value, int index, WrapperOptions options) throws SQLException {
+ if ( value == null ) {
+ st.setNull( index, Types.STRUCT, SDOGeometry.getTypeName());
+ }
+ else {
+ Geometry jtsGeom = (Geometry) value;
+ Object dbGeom = toNative( jtsGeom, st.getConnection() );
+ st.setObject( index, dbGeom );
+ }
+ }
+
+ public MGeometryFactory getGeometryFactory() {
+ return HBSpatialExtension.getDefaultGeomFactory();
+ }
+
+ private Object toNative(Geometry jtsGeom, Connection connection){
+ SDOGeometry geom = convertJTSGeometry(jtsGeom);
+ if (geom != null)
+ try {
+ return SDOGeometry.store(geom, connection);
+ } catch (SQLException e) {
+ throw new HibernateException(
+ "Problem during conversion from JTS to SDOGeometry", e);
+ } catch (FinderException e) {
+ throw new HibernateException(
+ "OracleConnection could not be retrieved for creating SDOGeometry STRUCT", e);
+ }
+ else {
+ throw new UnsupportedOperationException("Conversion of "
+ + jtsGeom.getClass().getSimpleName()
+ + " to Oracle STRUCT not supported");
+ }
+ }
+
+ private SDOGeometry convertJTSGeometry(Geometry jtsGeom) {
+ SDOGeometry geom = null;
+ if (jtsGeom instanceof Point ) {
+ geom = convertJTSPoint((Point) jtsGeom);
+ } else if (jtsGeom instanceof LineString ) {
+ geom = convertJTSLineString((LineString) jtsGeom);
+ } else if (jtsGeom instanceof Polygon ) {
+ geom = convertJTSPolygon((Polygon) jtsGeom);
+ } else if (jtsGeom instanceof MultiPoint ) {
+ geom = convertJTSMultiPoint((MultiPoint) jtsGeom);
+ } else if (jtsGeom instanceof MultiLineString ) {
+ geom = convertJTSMultiLineString((MultiLineString) jtsGeom);
+ } else if (jtsGeom instanceof MultiPolygon ) {
+ geom = convertJTSMultiPolygon((MultiPolygon) jtsGeom);
+ } else if (jtsGeom instanceof GeometryCollection ) {
+ geom = convertJTSGeometryCollection((GeometryCollection) jtsGeom);
+ }
+ return geom;
+ }
+
+ private SDOGeometry convertJTSGeometryCollection(
+ GeometryCollection collection) {
+ SDOGeometry[] SDOElements = new SDOGeometry[collection
+ .getNumGeometries()];
+ for (int i = 0; i < collection.getNumGeometries(); i++) {
+ Geometry geom = collection.getGeometryN(i);
+ SDOElements[i] = convertJTSGeometry(geom);
+ }
+ SDOGeometry ccollect = SDOGeometry.join(SDOElements);
+ ccollect.setSRID(collection.getSRID());
+ return ccollect;
+ }
+
+ private SDOGeometry convertJTSMultiPolygon(MultiPolygon multiPolygon) {
+ int dim = getCoordDimension(multiPolygon);
+ int lrsPos = getCoordinateLrsPosition(multiPolygon);
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(new SDOGType(dim, lrsPos, TypeGeometry.MULTIPOLYGON));
+ geom.setSRID(multiPolygon.getSRID());
+ for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
+ try {
+ Polygon pg = (Polygon) multiPolygon.getGeometryN(i);
+ addPolygon(geom, pg);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Found geometry that was not a geometry in MultiPolygon");
+ }
+ }
+ return geom;
+ }
+
+ private SDOGeometry convertJTSLineString(LineString lineString) {
+ int dim = getCoordDimension(lineString);
+ int lrsPos = getCoordinateLrsPosition(lineString);
+ boolean isLrs = lrsPos > 0;
+ Double[] ordinates = convertCoordinates(lineString.getCoordinates(),
+ dim, isLrs);
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(new SDOGType(dim, lrsPos, TypeGeometry.LINE));
+ geom.setSRID(lineString.getSRID());
+ ElemInfo info = new ElemInfo(1);
+ info.setElement(0, 1, ElementType.LINE_STRAITH_SEGMENTS, 0);
+ geom.setInfo(info);
+ geom.setOrdinates(new Ordinates(ordinates));
+ return geom;
+
+ }
+
+ private SDOGeometry convertJTSMultiPoint(MultiPoint multiPoint) {
+ int dim = getCoordDimension(multiPoint);
+ int lrsDim = getCoordinateLrsPosition(multiPoint);
+ boolean isLrs = (lrsDim != 0);
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(new SDOGType(dim, lrsDim, TypeGeometry.MULTIPOINT));
+ geom.setSRID(multiPoint.getSRID());
+ ElemInfo info = new ElemInfo(multiPoint.getNumPoints());
+ int oordinatesOffset = 1;
+ Double[] ordinates = new Double[]{};
+ for (int i = 0; i < multiPoint.getNumPoints(); i++) {
+ info.setElement(i, oordinatesOffset, ElementType.POINT, 0);
+ ordinates = convertAddCoordinates(ordinates, multiPoint
+ .getGeometryN(i).getCoordinates(), dim, isLrs);
+ oordinatesOffset = ordinates.length + 1;
+ }
+ geom.setInfo(info);
+ geom.setOrdinates(new Ordinates(ordinates));
+ return geom;
+ }
+
+ private SDOGeometry convertJTSPoint(Point jtsGeom) {
+ int dim = getCoordDimension(jtsGeom);
+
+ int lrsDim = getCoordinateLrsPosition(jtsGeom);
+ boolean isLrs = (lrsDim != 0);
+
+ Double[] coord = convertCoordinates(jtsGeom.getCoordinates(), dim,
+ isLrs);
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(new SDOGType(dim, lrsDim, TypeGeometry.POINT));
+ geom.setSRID(jtsGeom.getSRID());
+ ElemInfo info = new ElemInfo(1);
+ info.setElement(0, 1, ElementType.POINT, 1);
+ geom.setInfo(info);
+ geom.setOrdinates(new Ordinates(coord));
+ return geom;
+ }
+
+ private SDOGeometry convertJTSPolygon(Polygon polygon) {
+ int dim = getCoordDimension(polygon);
+ int lrsPos = getCoordinateLrsPosition(polygon);
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(new SDOGType(dim, lrsPos, TypeGeometry.POLYGON));
+ geom.setSRID(polygon.getSRID());
+ addPolygon(geom, polygon);
+ return geom;
+ }
+
+ private void addPolygon(SDOGeometry geom, Polygon polygon) {
+ int numInteriorRings = polygon.getNumInteriorRing();
+ ElemInfo info = new ElemInfo(numInteriorRings + 1);
+ int ordinatesPreviousOffset = 0;
+ if (geom.getOrdinates() != null) {
+ ordinatesPreviousOffset = geom.getOrdinates().getOrdinateArray().length;
+ }
+ int ordinatesOffset = ordinatesPreviousOffset + 1;
+ Double[] ordinates = new Double[]{};
+ for (int i = 0; i < info.getSize(); i++) {
+ ElementType et;
+ Coordinate[] coords;
+ if (i == 0) {
+ et = ElementType.EXTERIOR_RING_STRAIGHT_SEGMENTS;
+ coords = polygon.getExteriorRing().getCoordinates();
+ if (!CGAlgorithms.isCCW( coords )) {
+ coords = reverseRing(coords);
+ }
+ } else {
+ et = ElementType.INTERIOR_RING_STRAIGHT_SEGMENTS;
+ coords = polygon.getInteriorRingN(i - 1).getCoordinates();
+ if (CGAlgorithms.isCCW(coords)) {
+ coords = reverseRing(coords);
+ }
+ }
+ info.setElement(i, ordinatesOffset, et, 0);
+ ordinates = convertAddCoordinates(ordinates, coords, geom
+ .getDimension(), geom.isLRSGeometry());
+ ordinatesOffset = ordinatesPreviousOffset + ordinates.length + 1;
+ }
+ geom.addElement(info);
+ geom.addOrdinates(ordinates);
+ }
+
+ private SDOGeometry convertJTSMultiLineString(
+ MultiLineString multiLineString) {
+ int dim = getCoordDimension(multiLineString);
+ int lrsDim = getCoordinateLrsPosition(multiLineString);
+ boolean isLrs = (lrsDim != 0);
+ SDOGeometry geom = new SDOGeometry();
+ geom.setGType(new SDOGType(dim, lrsDim, TypeGeometry.MULTILINE));
+ geom.setSRID(multiLineString.getSRID());
+ ElemInfo info = new ElemInfo(multiLineString.getNumGeometries());
+ int oordinatesOffset = 1;
+ Double[] ordinates = new Double[]{};
+ for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
+ info.setElement(i, oordinatesOffset,
+ ElementType.LINE_STRAITH_SEGMENTS, 0);
+ ordinates = convertAddCoordinates(ordinates, multiLineString
+ .getGeometryN(i).getCoordinates(), dim, isLrs);
+ oordinatesOffset = ordinates.length + 1;
+ }
+ geom.setInfo(info);
+ geom.setOrdinates(new Ordinates(ordinates));
+ return geom;
+ }
+
+ private Double[] convertAddCoordinates(Double[] ordinates,
+ Coordinate[] coordinates, int dim, boolean isLrs) {
+ Double[] no = convertCoordinates(coordinates, dim, isLrs);
+ Double[] newordinates = new Double[ordinates.length + no.length];
+ System.arraycopy(ordinates, 0, newordinates, 0, ordinates.length);
+ System.arraycopy(no, 0, newordinates, ordinates.length, no.length);
+ return newordinates;
+ }
+
+ /**
+ * Convert the coordinates to a double array for purposes of persisting them
+ * to the database. Note that Double.NaN values are to be converted to null
+ * values in the array.
+ *
+ * @param coordinates Coordinates to be converted to the array
+ * @param dim Coordinate dimension
+ * @param isLrs true if the coordinates contain measures
+ * @return
+ */
+ private Double[] convertCoordinates(Coordinate[] coordinates, int dim,
+ boolean isLrs) {
+ if (dim > 4)
+ throw new IllegalArgumentException(
+ "Dim parameter value cannot be greater than 4");
+ Double[] converted = new Double[coordinates.length * dim];
+ for (int i = 0; i < coordinates.length; i++) {
+ MCoordinate c = MCoordinate.convertCoordinate(coordinates[i]);
+
+ // set the X and Y values
+ converted[i * dim] = toDouble(c.x);
+ converted[i * dim + 1] = toDouble(c.y);
+ if (dim == 3)
+ converted[i * dim + 2] = isLrs ? toDouble(c.m) : toDouble(c.z);
+ else if (dim == 4) {
+ converted[i * dim + 2] = toDouble(c.z);
+ converted[i * dim + 3] = toDouble(c.m);
+ }
+ }
+ return converted;
+ }
+
+ /**
+ * This method converts a double primitive to a Double wrapper instance, but
+ * treats a Double.NaN value as null.
+ *
+ * @param d the value to be converted
+ * @return A Double instance of d, Null if the parameter is Double.NaN
+ */
+ private Double toDouble(double d) {
+ return Double.isNaN(d) ? null : d;
+ }
+
+ /**
+ * Return the dimension required for building the gType in the SDOGeometry
+ * object. Has support for LRS type geometries.
+ *
+ * @param geom and instance of the Geometry class from which the dimension is
+ * being extracted.
+ * @return number of dimensions for purposes of creating the
+ * SDOGeometry.SDOGType
+ */
+ private int getCoordDimension(Geometry geom) {
+ // This is awkward, I have to create an MCoordinate to discover what the
+ // dimension is.
+ // This shall be cleaner if MCoordinate.getOrdinate(int ordinateIndex)
+ // is moved to the
+ // Coordinate class
+ MCoordinate c = MCoordinate.convertCoordinate(geom.getCoordinate());
+ int d = 0;
+ if (c != null) {
+ if (!Double.isNaN(c.x))
+ d++;
+ if (!Double.isNaN(c.y))
+ d++;
+ if (!Double.isNaN(c.z))
+ d++;
+ if (!Double.isNaN(c.m))
+ d++;
+ }
+ return d;
+ }
+
+ /**
+ * Returns the lrs measure position for purposes of building the gType for
+ * an oracle geometry. At this point and time, I'll have to assume that the
+ * measure is always put at the end of the ordinate tuple, even though it
+ * technically wouldn't have to. This method bases its decision on whether
+ * the first coordinate has a measure value, as measure are required for the
+ * very first and last measure in a CoordinateSequence. If there is no
+ * measure value, 0 is returned.
+ *
+ * @param geom and instance of the Geometry class from which the lrs position
+ * is being extracted.
+ * @return the lrs position for the SDOGeometry.SDOGType
+ */
+ private int getCoordinateLrsPosition(Geometry geom) {
+ MCoordinate c = MCoordinate.convertCoordinate( geom.getCoordinate() );
+ int measurePos = 0;
+ if (c != null && !Double.isNaN(c.m)) {
+ measurePos = (Double.isNaN(c.z)) ? 3 : 4;
+ }
+ return measurePos;
+ }
+
+ // reverses ordinates in a coordinate array in-place
+
+ private Coordinate[] reverseRing(Coordinate[] ar) {
+ for (int i = 0; i < ar.length / 2; i++) {
+ Coordinate cs = ar[i];
+ ar[i] = ar[ar.length - 1 - i];
+ ar[ar.length - 1 - i] = cs;
+ }
+ return ar;
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java
new file mode 100644
index 0000000000..b7c9133f09
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java
@@ -0,0 +1,522 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Struct;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.CoordinateSequence;
+import com.vividsolutions.jts.geom.Geometry;
+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 org.hibernate.HibernateException;
+import org.hibernate.spatial.Circle;
+import org.hibernate.spatial.HBSpatialExtension;
+import org.hibernate.spatial.mgeom.MCoordinate;
+import org.hibernate.spatial.mgeom.MGeometryFactory;
+import org.hibernate.spatial.mgeom.MLineString;
+import org.hibernate.type.descriptor.ValueExtractor;
+import org.hibernate.type.descriptor.WrapperOptions;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: 8/22/11
+ */
+public class SDOGeometryValueExtractor implements ValueExtractor {
+
+ @Override
+ public Geometry extract(ResultSet rs, String name, WrapperOptions options)
+ throws SQLException {
+ Object geomObj = rs.getObject( name );
+ return toJTS( geomObj );
+ }
+
+ public MGeometryFactory getGeometryFactory() {
+ return HBSpatialExtension.getDefaultGeomFactory();
+ }
+
+ public Geometry toJTS(Object struct) {
+ if ( struct == null ) {
+ return null;
+ }
+ SDOGeometry SDOGeom = SDOGeometry.load( (Struct) struct );
+ return convert2JTS( SDOGeom );
+ }
+
+ private Geometry convert2JTS(SDOGeometry SDOGeom) {
+ int dim = SDOGeom.getGType().getDimension();
+ int lrsDim = SDOGeom.getGType().getLRSDimension();
+ Geometry result = null;
+ switch ( SDOGeom.getGType().getTypeGeometry() ) {
+ case POINT:
+ result = convertSDOPoint( SDOGeom );
+ break;
+ case LINE:
+ result = convertSDOLine( dim, lrsDim, SDOGeom );
+ break;
+ case POLYGON:
+ result = convertSDOPolygon( dim, lrsDim, SDOGeom );
+ break;
+ case MULTIPOINT:
+ result = convertSDOMultiPoint( dim, lrsDim, SDOGeom );
+ break;
+ case MULTILINE:
+ result = convertSDOMultiLine( dim, lrsDim, SDOGeom );
+ break;
+ case MULTIPOLYGON:
+ result = convertSDOMultiPolygon( dim, lrsDim, SDOGeom );
+ break;
+ case COLLECTION:
+ result = convertSDOCollection( dim, lrsDim, SDOGeom );
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Type not supported: "
+ + SDOGeom.getGType().getTypeGeometry()
+ );
+ }
+ result.setSRID( SDOGeom.getSRID() );
+ return result;
+
+ }
+
+ private Geometry convertSDOCollection(int dim, int lrsDim,
+ SDOGeometry SDOGeom) {
+ List geometries = new ArrayList();
+ for ( SDOGeometry elemGeom : SDOGeom.getElementGeometries() ) {
+ geometries.add( convert2JTS( elemGeom ) );
+ }
+ Geometry[] geomArray = new Geometry[geometries.size()];
+ return getGeometryFactory().createGeometryCollection(
+ geometries.toArray( geomArray )
+ );
+ }
+
+ private Point convertSDOPoint(SDOGeometry SDOGeom) {
+ Double[] ordinates = SDOGeom.getOrdinates().getOrdinateArray();
+ if ( ordinates.length == 0 ) {
+ if ( SDOGeom.getDimension() == 2 ) {
+ ordinates = new Double[] {
+ SDOGeom.getPoint().x,
+ SDOGeom.getPoint().y
+ };
+ }
+ else {
+ ordinates = new Double[] {
+ SDOGeom.getPoint().x,
+ SDOGeom.getPoint().y, SDOGeom.getPoint().z
+ };
+ }
+ }
+ CoordinateSequence cs = convertOrdinateArray( ordinates, SDOGeom );
+ Point point = getGeometryFactory().createPoint( cs );
+ return point;
+ }
+
+ private MultiPoint convertSDOMultiPoint(int dim, int lrsDim,
+ SDOGeometry SDOGeom) {
+ Double[] ordinates = SDOGeom.getOrdinates().getOrdinateArray();
+ CoordinateSequence cs = convertOrdinateArray( ordinates, SDOGeom );
+ MultiPoint multipoint = getGeometryFactory().createMultiPoint( cs );
+ return multipoint;
+ }
+
+ private LineString convertSDOLine(int dim, int lrsDim, SDOGeometry SDOGeom) {
+ boolean lrs = SDOGeom.isLRSGeometry();
+ ElemInfo info = SDOGeom.getInfo();
+ CoordinateSequence cs = null;
+
+ int i = 0;
+ while ( i < info.getSize() ) {
+ if ( info.getElementType( i ).isCompound() ) {
+ int numCompounds = info.getNumCompounds( i );
+ cs = add( cs, getCompoundCSeq( i + 1, i + numCompounds, SDOGeom ) );
+ i += 1 + numCompounds;
+ }
+ else {
+ cs = add( cs, getElementCSeq( i, SDOGeom, false ) );
+ i++;
+ }
+ }
+
+ LineString ls = lrs ? getGeometryFactory().createMLineString( cs )
+ : getGeometryFactory().createLineString( cs );
+ return ls;
+ }
+
+ private MultiLineString convertSDOMultiLine(int dim, int lrsDim,
+ SDOGeometry SDOGeom) {
+ boolean lrs = SDOGeom.isLRSGeometry();
+ ElemInfo info = SDOGeom.getInfo();
+ LineString[] lines = lrs ? new MLineString[SDOGeom.getInfo().getSize()]
+ : new LineString[SDOGeom.getInfo().getSize()];
+ int i = 0;
+ while ( i < info.getSize() ) {
+ CoordinateSequence cs = null;
+ if ( info.getElementType( i ).isCompound() ) {
+ int numCompounds = info.getNumCompounds( i );
+ cs = add( cs, getCompoundCSeq( i + 1, i + numCompounds, SDOGeom ) );
+ LineString line = lrs ? getGeometryFactory().createMLineString(
+ cs
+ ) : getGeometryFactory().createLineString( cs );
+ lines[i] = line;
+ i += 1 + numCompounds;
+ }
+ else {
+ cs = add( cs, getElementCSeq( i, SDOGeom, false ) );
+ LineString line = lrs ? getGeometryFactory().createMLineString(
+ cs
+ ) : getGeometryFactory().createLineString( cs );
+ lines[i] = line;
+ i++;
+ }
+ }
+
+ MultiLineString mls = lrs ? getGeometryFactory()
+ .createMultiMLineString( (MLineString[]) lines )
+ : getGeometryFactory().createMultiLineString( lines );
+ return mls;
+
+ }
+
+ private Geometry convertSDOPolygon(int dim, int lrsDim, SDOGeometry SDOGeom) {
+ LinearRing shell = null;
+ LinearRing[] holes = new LinearRing[SDOGeom.getNumElements() - 1];
+ ElemInfo info = SDOGeom.getInfo();
+ int i = 0;
+ int idxInteriorRings = 0;
+ while ( i < info.getSize() ) {
+ CoordinateSequence cs = null;
+ int numCompounds = 0;
+ if ( info.getElementType( i ).isCompound() ) {
+ numCompounds = info.getNumCompounds( i );
+ cs = add( cs, getCompoundCSeq( i + 1, i + numCompounds, SDOGeom ) );
+ }
+ else {
+ cs = add( cs, getElementCSeq( i, SDOGeom, false ) );
+ }
+ if ( info.getElementType( i ).isInteriorRing() ) {
+ holes[idxInteriorRings] = getGeometryFactory()
+ .createLinearRing( cs );
+ idxInteriorRings++;
+ }
+ else {
+ shell = getGeometryFactory().createLinearRing( cs );
+ }
+ i += 1 + numCompounds;
+ }
+ return getGeometryFactory().createPolygon( shell, holes );
+ }
+
+ private MultiPolygon convertSDOMultiPolygon(int dim, int lrsDim,
+ SDOGeometry SDOGeom) {
+ List holes = new ArrayList();
+ List polygons = new ArrayList();
+ ElemInfo info = SDOGeom.getInfo();
+ LinearRing shell = null;
+ int i = 0;
+ while ( i < info.getSize() ) {
+ CoordinateSequence cs = null;
+ int numCompounds = 0;
+ if ( info.getElementType( i ).isCompound() ) {
+ numCompounds = info.getNumCompounds( i );
+ cs = add( cs, getCompoundCSeq( i + 1, i + numCompounds, SDOGeom ) );
+ }
+ else {
+ cs = add( cs, getElementCSeq( i, SDOGeom, false ) );
+ }
+ if ( info.getElementType( i ).isInteriorRing() ) {
+ LinearRing lr = getGeometryFactory().createLinearRing( cs );
+ holes.add( lr );
+ }
+ else {
+ if ( shell != null ) {
+ Polygon polygon = getGeometryFactory().createPolygon(
+ shell,
+ holes.toArray( new LinearRing[holes.size()] )
+ );
+ polygons.add( polygon );
+ shell = null;
+ }
+ shell = getGeometryFactory().createLinearRing( cs );
+ holes = new ArrayList();
+ }
+ i += 1 + numCompounds;
+ }
+ if ( shell != null ) {
+ Polygon polygon = getGeometryFactory().createPolygon(
+ shell,
+ holes.toArray( new LinearRing[holes.size()] )
+ );
+ polygons.add( polygon );
+ }
+ MultiPolygon multiPolygon = getGeometryFactory().createMultiPolygon(
+ polygons.toArray( new Polygon[polygons.size()] )
+ );
+ return multiPolygon;
+ }
+
+ /**
+ * Gets the CoordinateSequence corresponding to a compound element.
+ *
+ * @param idxFirst the first sub-element of the compound element
+ * @param idxLast the last sub-element of the compound element
+ * @param SDOGeom the SDOGeometry that holds the compound element.
+ *
+ * @return
+ */
+ private CoordinateSequence getCompoundCSeq(int idxFirst, int idxLast,
+ SDOGeometry SDOGeom) {
+ CoordinateSequence cs = null;
+ for ( int i = idxFirst; i <= idxLast; i++ ) {
+ // pop off the last element as it is added with the next
+ // coordinate sequence
+ if ( cs != null && cs.size() > 0 ) {
+ Coordinate[] coordinates = cs.toCoordinateArray();
+ Coordinate[] newCoordinates = new Coordinate[coordinates.length - 1];
+ System.arraycopy(
+ coordinates, 0, newCoordinates, 0,
+ coordinates.length - 1
+ );
+ cs = getGeometryFactory().getCoordinateSequenceFactory()
+ .create( newCoordinates );
+ }
+ cs = add( cs, getElementCSeq( i, SDOGeom, ( i < idxLast ) ) );
+ }
+ return cs;
+ }
+
+ /**
+ * Gets the CoordinateSequence corresponding to an element.
+ *
+ * @param i
+ * @param SDOGeom
+ *
+ * @return
+ */
+ private CoordinateSequence getElementCSeq(int i, SDOGeometry SDOGeom,
+ boolean hasNextSE) {
+ ElementType type = SDOGeom.getInfo().getElementType( i );
+ Double[] elemOrdinates = extractOrdinatesOfElement(
+ i, SDOGeom,
+ hasNextSE
+ );
+ CoordinateSequence cs;
+ if ( type.isStraightSegment() ) {
+ cs = convertOrdinateArray( elemOrdinates, SDOGeom );
+ }
+ else if ( type.isArcSegment() || type.isCircle() ) {
+ Coordinate[] linearized = linearize(
+ elemOrdinates, SDOGeom
+ .getDimension(), SDOGeom.isLRSGeometry(), type.isCircle()
+ );
+ cs = getGeometryFactory().getCoordinateSequenceFactory().create(
+ linearized
+ );
+ }
+ else if ( type.isRect() ) {
+ cs = convertOrdinateArray( elemOrdinates, SDOGeom );
+ Coordinate ll = cs.getCoordinate( 0 );
+ Coordinate ur = cs.getCoordinate( 1 );
+ Coordinate lr = new Coordinate( ur.x, ll.y );
+ Coordinate ul = new Coordinate( ll.x, ur.y );
+ if ( type.isExteriorRing() ) {
+ cs = getGeometryFactory().getCoordinateSequenceFactory()
+ .create( new Coordinate[] { ll, lr, ur, ul, ll } );
+ }
+ else {
+ cs = getGeometryFactory().getCoordinateSequenceFactory()
+ .create( new Coordinate[] { ll, ul, ur, lr, ll } );
+ }
+ }
+ else {
+ throw new RuntimeException(
+ "Unexpected Element type in compound: "
+ + type
+ );
+ }
+ return cs;
+ }
+
+ private CoordinateSequence add(CoordinateSequence seq1,
+ CoordinateSequence seq2) {
+ if ( seq1 == null ) {
+ return seq2;
+ }
+ if ( seq2 == null ) {
+ return seq1;
+ }
+ Coordinate[] c1 = seq1.toCoordinateArray();
+ Coordinate[] c2 = seq2.toCoordinateArray();
+ Coordinate[] c3 = new Coordinate[c1.length + c2.length];
+ System.arraycopy( c1, 0, c3, 0, c1.length );
+ System.arraycopy( c2, 0, c3, c1.length, c2.length );
+ return getGeometryFactory().getCoordinateSequenceFactory().create( c3 );
+ }
+
+ private Double[] extractOrdinatesOfElement(int element,
+ SDOGeometry SDOGeom, boolean hasNextSE) {
+ int start = SDOGeom.getInfo().getOrdinatesOffset( element );
+ if ( element < SDOGeom.getInfo().getSize() - 1 ) {
+ int end = SDOGeom.getInfo().getOrdinatesOffset( element + 1 );
+ // if this is a subelement of a compound geometry,
+ // the last point is the first point of
+ // the next subelement.
+ if ( hasNextSE ) {
+ end += SDOGeom.getDimension();
+ }
+ return SDOGeom.getOrdinates().getOrdinatesArray( start, end );
+ }
+ else {
+ return SDOGeom.getOrdinates().getOrdinatesArray( start );
+ }
+ }
+
+ private CoordinateSequence convertOrdinateArray(Double[] oordinates,
+ SDOGeometry SDOGeom) {
+ int dim = SDOGeom.getDimension();
+ Coordinate[] coordinates = new Coordinate[oordinates.length / dim];
+ int zDim = SDOGeom.getZDimension() - 1;
+ int lrsDim = SDOGeom.getLRSDimension() - 1;
+ for ( int i = 0; i < coordinates.length; i++ ) {
+ if ( dim == 2 ) {
+ coordinates[i] = new Coordinate(
+ oordinates[i * dim],
+ oordinates[i * dim + 1]
+ );
+ }
+ else if ( dim == 3 ) {
+ if ( SDOGeom.isLRSGeometry() ) {
+ coordinates[i] = MCoordinate.create2dWithMeasure(
+ oordinates[i * dim], // X
+ oordinates[i * dim + 1], // Y
+ oordinates[i * dim + lrsDim]
+ ); // M
+ }
+ else {
+ coordinates[i] = new Coordinate(
+ oordinates[i * dim], // X
+ oordinates[i * dim + 1], // Y
+ oordinates[i * dim + zDim]
+ ); // Z
+ }
+ }
+ else if ( dim == 4 ) {
+ // This must be an LRS Geometry
+ if ( !SDOGeom.isLRSGeometry() ) {
+ throw new HibernateException(
+ "4 dimensional Geometries must be LRS geometry"
+ );
+ }
+ coordinates[i] = MCoordinate.create3dWithMeasure(
+ oordinates[i
+ * dim], // X
+ oordinates[i * dim + 1], // Y
+ oordinates[i * dim + zDim], // Z
+ oordinates[i * dim + lrsDim]
+ ); // M
+ }
+ }
+ return getGeometryFactory().getCoordinateSequenceFactory().create(
+ coordinates
+ );
+ }
+
+
+ /**
+ * Linearizes arcs and circles.
+ *
+ * @param arcOrdinates arc or circle coordinates
+ * @param dim coordinate dimension
+ * @param lrs whether this is an lrs geometry
+ * @param entireCirlce whether the whole arc should be linearized
+ *
+ * @return linearized interpolation of arcs or circle
+ */
+ private Coordinate[] linearize(Double[] arcOrdinates, int dim, boolean lrs,
+ boolean entireCirlce) {
+ Coordinate[] linearizedCoords = new Coordinate[0];
+ // CoordDim is the dimension that includes only non-measure (X,Y,Z)
+ // ordinates in its value
+ int coordDim = lrs ? dim - 1 : dim;
+ // this only works with 2-Dimensional geometries, since we use
+ // JGeometry linearization;
+ if ( coordDim != 2 ) {
+ throw new IllegalArgumentException(
+ "Can only linearize 2D arc segments, but geometry is "
+ + dim + "D."
+ );
+ }
+ int numOrd = dim;
+ while ( numOrd < arcOrdinates.length ) {
+ numOrd = numOrd - dim;
+ double x1 = arcOrdinates[numOrd++];
+ double y1 = arcOrdinates[numOrd++];
+ double m1 = lrs ? arcOrdinates[numOrd++] : Double.NaN;
+ double x2 = arcOrdinates[numOrd++];
+ double y2 = arcOrdinates[numOrd++];
+ double m2 = lrs ? arcOrdinates[numOrd++] : Double.NaN;
+ double x3 = arcOrdinates[numOrd++];
+ double y3 = arcOrdinates[numOrd++];
+ double m3 = lrs ? arcOrdinates[numOrd++] : Double.NaN;
+
+ Coordinate[] coords;
+ if ( entireCirlce ) {
+ coords = Circle.linearizeCircle( x1, y1, x2, y2, x3, y3 );
+ }
+ else {
+ coords = Circle.linearizeArc( x1, y1, x2, y2, x3, y3 );
+ }
+
+ // if this is an LRS geometry, fill the measure values into
+ // the linearized array
+ if ( lrs ) {
+ MCoordinate[] mcoord = new MCoordinate[coords.length];
+ int lastIndex = coords.length - 1;
+ mcoord[0] = MCoordinate.create2dWithMeasure( x1, y1, m1 );
+ mcoord[lastIndex] = MCoordinate.create2dWithMeasure( x3, y3, m3 );
+ // convert the middle coordinates to MCoordinate
+ for ( int i = 1; i < lastIndex; i++ ) {
+ mcoord[i] = MCoordinate.convertCoordinate( coords[i] );
+ // if we happen to split on the middle measure, then
+ // assign it
+ if ( Double.compare( mcoord[i].x, x2 ) == 0
+ && Double.compare( mcoord[i].y, y2 ) == 0 ) {
+ mcoord[i].m = m2;
+ }
+ }
+ coords = mcoord;
+ }
+
+ // if this is not the first arcsegment, the first linearized
+ // point is already in linearizedArc, so disregard this.
+ int resultBegin = 1;
+ if ( linearizedCoords.length == 0 ) {
+ resultBegin = 0;
+ }
+
+ int destPos = linearizedCoords.length;
+ Coordinate[] tmpCoords = new Coordinate[linearizedCoords.length
+ + coords.length - resultBegin];
+ System.arraycopy(
+ linearizedCoords, 0, tmpCoords, 0,
+ linearizedCoords.length
+ );
+ System.arraycopy(
+ coords, resultBegin, tmpCoords, destPos,
+ coords.length - resultBegin
+ );
+
+ linearizedCoords = tmpCoords;
+ }
+ return linearizedCoords;
+ }
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectMethod.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectMethod.java
new file mode 100644
index 0000000000..1f3946164c
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectMethod.java
@@ -0,0 +1,109 @@
+/*
+ * $Id: SDOObjectMethod.java 268 2010-10-28 19:16:54Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle;
+
+import java.util.List;
+
+import org.hibernate.QueryException;
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.engine.spi.Mapping;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+
+/**
+ * Special SQLFunction implementation for Oracle object methods
+ *
+ * @author Karel Maesen
+ */
+class SDOObjectMethod implements SQLFunction {
+
+ private final Type type;
+
+ private final String name;
+
+ public SDOObjectMethod(String name, Type type) {
+ this.type = type;
+ this.name = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#getReturnType(org.hibernate.type.Type,
+ * org.hibernate.engine.Mapping)
+ */
+
+ public Type getReturnType(Type columnType, Mapping mapping)
+ throws QueryException {
+ return type == null ? columnType : type;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#hasArguments()
+ */
+
+ public boolean hasArguments() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#hasParenthesesIfNoArguments()
+ */
+
+ public boolean hasParenthesesIfNoArguments() {
+ return true;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#render(java.util.List,
+ * org.hibernate.engine.SessionFactoryImplementor)
+ */
+
+ public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
+ StringBuffer buf = new StringBuffer();
+ if (args.isEmpty())
+ throw new QueryException(
+ "First Argument in arglist must be object to which method is applied");
+ buf.append(args.get(0)).append(".").append(name).append('(');
+ for (int i = 1; i < args.size(); i++) {
+ buf.append(args.get(i));
+ if (i < args.size() - 1) {
+ buf.append(", ");
+ }
+ }
+ return buf.append(')').toString();
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectProperty.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectProperty.java
new file mode 100644
index 0000000000..696c7b6ee0
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOObjectProperty.java
@@ -0,0 +1,104 @@
+/*
+ * $Id: SDOObjectProperty.java 268 2010-10-28 19:16:54Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle;
+
+import java.util.List;
+
+import org.hibernate.QueryException;
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.engine.spi.Mapping;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+
+/**
+ * Special function for accessing a member variable of an Oracle Object
+ *
+ * @author Karel Maesen
+ */
+class SDOObjectProperty implements SQLFunction {
+
+ private final Type type;
+
+ private final String name;
+
+ public SDOObjectProperty(String name, Type type) {
+ this.type = type;
+ this.name = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#getReturnType(org.hibernate.type.Type,
+ * org.hibernate.engine.Mapping)
+ */
+
+ public Type getReturnType(Type columnType, Mapping mapping)
+ throws QueryException {
+ return type == null ? columnType : type;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#hasArguments()
+ */
+
+ public boolean hasArguments() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#hasParenthesesIfNoArguments()
+ */
+
+ public boolean hasParenthesesIfNoArguments() {
+ return false;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.dialect.function.SQLFunction#render(java.util.List,
+ * org.hibernate.engine.SessionFactoryImplementor)
+ */
+
+ public String render(Type firstArgtype, List args, SessionFactoryImplementor factory)
+ throws QueryException {
+ StringBuffer buf = new StringBuffer();
+ if (args.isEmpty())
+ throw new QueryException(
+ "First Argument in arglist must be object of which property is queried");
+ buf.append(args.get(0)).append(".").append(name);
+ return buf.toString();
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOPoint.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOPoint.java
new file mode 100644
index 0000000000..7c7042cb29
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOPoint.java
@@ -0,0 +1,37 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.SQLException;
+import java.sql.Struct;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 1, 2010
+ */
+class SDOPoint {
+ public double x = 0.0;
+
+ public double y = 0.0;
+
+ public double z = Double.NaN;
+
+ public SDOPoint(Struct struct) {
+ try {
+ Object[] data = struct.getAttributes();
+ this.x = ((Number) data[0]).doubleValue();
+ this.y = ((Number) data[1]).doubleValue();
+ if (data[2] != null) {
+ this.z = ((Number) data[1]).doubleValue();
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String toString() {
+ StringBuilder stb = new StringBuilder();
+ stb.append("(").append(x).append(",").append(y).append(",").append(
+ z).append(")");
+ return stb.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SpatialAggregate.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SpatialAggregate.java
new file mode 100644
index 0000000000..3e8996de17
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SpatialAggregate.java
@@ -0,0 +1,91 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+
+import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate;
+
+/**
+ * Provides Aggregate type spatial function interpretation
+ */
+class SpatialAggregate {
+
+ boolean _aggregateType;
+
+ String _aggregateSyntax;
+
+ private final String SDO_AGGR = "SDO_AGGR_";
+
+ SpatialAggregate() {
+ }
+
+ SpatialAggregate(int aggregation) {
+
+ String specificAggrSyntax;
+
+ switch (aggregation) {
+ case org.hibernate.spatial.SpatialAggregate.EXTENT:
+ specificAggrSyntax = "MBR";
+ _aggregateType = false;
+ break;
+ case OracleSpatialAggregate.LRS_CONCAT:
+ specificAggrSyntax = "LRS_CONCAT";
+ _aggregateType = true;
+ break;
+ case OracleSpatialAggregate.CENTROID:
+ specificAggrSyntax = "CENTROID";
+ _aggregateType = true;
+ break;
+ case OracleSpatialAggregate.CONCAT_LINES:
+ specificAggrSyntax = "CONCAT_LINES";
+ _aggregateType = false;
+ break;
+ case OracleSpatialAggregate.UNION:
+ specificAggrSyntax = "UNION";
+ _aggregateType = true;
+ break;
+ case OracleSpatialAggregate.CONVEXHULL:
+ specificAggrSyntax = "CONVEXHULL";
+ _aggregateType = true;
+ break;
+ default:
+ specificAggrSyntax = null;
+ break;
+ }
+ if (specificAggrSyntax != null) {
+ _aggregateSyntax = SDO_AGGR + specificAggrSyntax;
+ }
+ }
+
+ public boolean isAggregateType() {
+ return _aggregateType;
+ }
+
+ public String getAggregateSyntax() {
+ return _aggregateSyntax;
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/StructLoader.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/StructLoader.java
new file mode 100644
index 0000000000..cbc25d879d
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/StructLoader.java
@@ -0,0 +1,20 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Struct;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 3, 2010
+ */
+interface SQLTypeFactory {
+
+ Struct createStruct(SDOGeometry geom, Connection conn) throws SQLException;
+
+ Array createElemInfoArray(ElemInfo elemInfo, Connection conn) throws SQLException;
+
+ Array createOrdinatesArray(Ordinates ordinates, Connection conn) throws SQLException;
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/TypeGeometry.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/TypeGeometry.java
new file mode 100644
index 0000000000..c4278dd3c2
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/TypeGeometry.java
@@ -0,0 +1,32 @@
+package org.hibernate.spatial.dialect.oracle;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jul 1, 2010
+ */
+enum TypeGeometry {
+
+ UNKNOWN_GEOMETRY(0), POINT(1), LINE(2), POLYGON(3), COLLECTION(4), MULTIPOINT(
+ 5), MULTILINE(6), MULTIPOLYGON(7), SOLID(8), MULTISOLID(9);
+
+ private int gtype = 0;
+
+ TypeGeometry(int gtype) {
+ this.gtype = gtype;
+ }
+
+ int intValue() {
+ return this.gtype;
+ }
+
+ static TypeGeometry parse(int v) {
+ for (TypeGeometry gt : values()) {
+ if (gt.intValue() == v) {
+ return gt;
+ }
+ }
+ throw new RuntimeException("Value " + v
+ + " isn't a valid TypeGeometry value");
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/WrappedOGCFunction.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/WrappedOGCFunction.java
new file mode 100644
index 0000000000..0e60ed1d20
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/WrappedOGCFunction.java
@@ -0,0 +1,77 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import java.util.List;
+
+import com.vividsolutions.jts.geom.Geometry;
+
+import org.hibernate.dialect.function.StandardSQLFunction;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+
+/**
+ * An HQL function that is implemented using Oracle's OGC compliance
+ * package.
+ */
+class WrappedOGCFunction extends StandardSQLFunction {
+ private final boolean[] geomArrays;
+
+ /**
+ * @param name function name
+ * @param type return type of the function
+ * @param geomArrays indicates which argument places are occupied by
+ * sdo_geometries
+ */
+ WrappedOGCFunction(final String name, final Type type,
+ final boolean[] geomArrays) {
+ super(name, type);
+ this.geomArrays = geomArrays;
+ }
+
+ public String render(Type firstArgumentType, final List args,
+ final SessionFactoryImplementor factory) {
+
+ StringBuffer buf = new StringBuffer();
+ buf.append("MDSYS.").append(getName()).append("(");
+ for (int i = 0; i < args.size(); i++) {
+ if (i > 0) {
+ buf.append(",");
+ }
+ if (geomArrays[i]) {
+ buf.append("MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(").append(
+ args.get(i)).append(")");
+ } else {
+ buf.append(args.get(i));
+ }
+
+ }
+ buf.append(")");
+ return (getType().getReturnedClass() == Geometry.class) ? buf
+ .append(".geom").toString() : buf.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialAggregate.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialAggregate.java
new file mode 100644
index 0000000000..7395c6b2aa
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialAggregate.java
@@ -0,0 +1,48 @@
+/**
+ * $Id: OracleSpatialAggregate.java 103 2008-08-15 10:45:29Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle.criterion;
+
+
+import org.hibernate.spatial.SpatialAggregate;
+
+/**
+ * Defines types of OracleSpatialAggregate
+ */
+public interface OracleSpatialAggregate extends SpatialAggregate {
+
+ public static int LRS_CONCAT = 100;
+
+ public static int CENTROID = 101;
+
+ public static int CONCAT_LINES = 102;
+
+ public static int UNION = 103;
+
+ public static int CONVEXHULL = 104;
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjection.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjection.java
new file mode 100644
index 0000000000..9907fa82df
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjection.java
@@ -0,0 +1,86 @@
+/**
+ * $Id: OracleSpatialProjection.java 268 2010-10-28 19:16:54Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle.criterion;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.criterion.CriteriaQuery;
+import org.hibernate.criterion.SimpleProjection;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.spatial.SpatialDialect;
+import org.hibernate.type.Type;
+
+/**
+ * Template class for Spatial Projections
+ *
+ * @author Tom Acree
+ */
+public class OracleSpatialProjection extends SimpleProjection {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String propertyName;
+
+ private final int aggregate;
+
+ public OracleSpatialProjection(int aggregate, String propertyName) {
+ this.propertyName = propertyName;
+ this.aggregate = aggregate;
+ }
+
+ public String toSqlString(Criteria criteria, int position,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+
+ SessionFactoryImplementor factory = criteriaQuery.getFactory();
+ String[] columns = criteriaQuery.getColumnsUsingProjection(criteria,
+ this.propertyName);
+ Dialect dialect = factory.getDialect();
+ if (dialect instanceof SpatialDialect) {
+ SpatialDialect seDialect = (SpatialDialect) dialect;
+
+ return new StringBuffer(seDialect.getSpatialAggregateSQL(
+ columns[0], this.aggregate)).append(" y").append(position)
+ .append("_").toString();
+ } else {
+ throw new IllegalStateException(
+ "Dialect must be spatially enabled dialect");
+ }
+
+ }
+
+ public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
+ throws HibernateException {
+ return new Type[]{criteriaQuery.getType(criteria, this.propertyName)};
+ }
+
+ public String toString() {
+ return aggregate + "(" + propertyName + ")";
+ }
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjections.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjections.java
new file mode 100644
index 0000000000..ab879358b4
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialProjections.java
@@ -0,0 +1,60 @@
+/**
+ * $Id: OracleSpatialProjections.java 67 2007-12-16 16:41:55Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle.criterion;
+
+/**
+ * Factory class for SpationProjection functions *
+ *
+ * @author Tom Acree
+ */
+public final class OracleSpatialProjections {
+
+ private OracleSpatialProjections() {
+ }
+
+ public static OracleSpatialProjection concatLrs(String propertyName) {
+ return new OracleSpatialProjection(OracleSpatialAggregate.LRS_CONCAT,
+ propertyName);
+ }
+
+ public static OracleSpatialProjection centroid(String propertyName) {
+ return new OracleSpatialProjection(OracleSpatialAggregate.CENTROID,
+ propertyName);
+ }
+
+ public static OracleSpatialProjection concatLines(String propertyName) {
+ return new OracleSpatialProjection(OracleSpatialAggregate.CONCAT_LINES,
+ propertyName);
+ }
+
+ public static OracleSpatialProjection projection(int projection,
+ String propertyName) {
+ return new OracleSpatialProjection(projection, propertyName);
+ }
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialRestrictions.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialRestrictions.java
new file mode 100644
index 0000000000..b70abaf3e5
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/OracleSpatialRestrictions.java
@@ -0,0 +1,204 @@
+/**
+ * $Id: OracleSpatialRestrictions.java 268 2010-10-28 19:16:54Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle.criterion;
+
+import com.vividsolutions.jts.geom.Geometry;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.criterion.CriteriaQuery;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.engine.spi.TypedValue;
+
+/**
+ * A static factory class for creating Criterion
instances that
+ * correspond to Oracle Spatial "native" spatial operators.
+ *
+ * @author Karel Maesen
+ */
+public class OracleSpatialRestrictions {
+
+ @SuppressWarnings("serial")
+ public static Criterion SDOFilter(String propertyName, Geometry geom,
+ SDOParameterMap param) {
+ return new OracleSpatialCriterion(propertyName, geom, param) {
+ @Override
+ public String toSqlString(Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ String[] columns = criteriaQuery.getColumnsUsingProjection(
+ criteria, this.propertyName);
+ StringBuilder sql = new StringBuilder("SDO_FILTER(");
+ sql.append(columns[0]).append(",").append("?");
+ if (param != null && !param.isEmpty()) {
+ sql.append(",").append(param.toQuotedString());
+ }
+ sql.append(") = 'TRUE'");
+ return sql.toString();
+ }
+ };
+ }
+
+ @SuppressWarnings("serial")
+ public static Criterion SDOFilter(String propertyName, Geometry geom,
+ Double minResolution, Double maxResolution) {
+ if (minResolution == null && maxResolution == null) {
+ return SDOFilter(propertyName, geom, null);
+ } else {
+ SDOParameterMap param = new SDOParameterMap();
+ param.setMinResolution(minResolution);
+ param.setMaxResolution(maxResolution);
+ return SDOFilter(propertyName, geom, param);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static Criterion SDONN(String propertyName, Geometry geom,
+ Double distance, Integer numResults, String unit) {
+ if (distance == null && numResults == null && unit == null) {
+ return SDONN(propertyName, geom, null);
+ } else {
+ SDOParameterMap param = new SDOParameterMap();
+ param.setDistance(distance);
+ param.setSdoNumRes(numResults);
+ param.setUnit(unit);
+ return SDONN(propertyName, geom, param);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static Criterion SDONN(String propertyName, Geometry geom,
+ SDOParameterMap param) {
+ return new OracleSpatialCriterion(propertyName, geom, param) {
+ @Override
+ public String toSqlString(Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ String[] columns = criteriaQuery.getColumnsUsingProjection(
+ criteria, this.propertyName);
+ StringBuilder sql = new StringBuilder("SDO_NN(");
+ sql.append(columns[0]).append(",").append("?");
+ if (param != null && !param.isEmpty()) {
+ sql.append(",").append(param.toQuotedString());
+ }
+ sql.append(") = 'TRUE'");
+ return sql.toString();
+ }
+ };
+ }
+
+ @SuppressWarnings("serial")
+ public static Criterion SDORelate(String propertyName, Geometry geom,
+ SDOParameterMap param) {
+ return new OracleSpatialCriterion(propertyName, geom, param) {
+ @Override
+ public String toSqlString(Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ String[] columns = criteriaQuery.getColumnsUsingProjection(
+ criteria, this.propertyName);
+ StringBuilder sql = new StringBuilder("SDO_RELATE(");
+ sql.append(columns[0]).append(",").append("?");
+ if (param != null && !param.isEmpty()) {
+ sql.append(",").append(param.toQuotedString());
+ }
+ sql.append(") = 'TRUE'");
+ return sql.toString();
+ }
+ };
+ }
+
+ @SuppressWarnings("serial")
+ public static Criterion SDORelate(String propertyName, Geometry geom,
+ RelationshipMask[] mask, Double minResolution, Double maxResolution) {
+ SDOParameterMap param = new SDOParameterMap();
+ param.setMask(RelationshipMask.booleanCombination(mask));
+ param.setMinResolution(minResolution);
+ param.setMaxResolution(maxResolution);
+ return SDORelate(propertyName, geom, param);
+ }
+
+ @SuppressWarnings("serial")
+ public static Criterion SDOWithinDistance(String propertyName,
+ Geometry geom, SDOParameterMap param) {
+ return new OracleSpatialCriterion(propertyName, geom, param) {
+
+ @Override
+ public String toSqlString(Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ String[] columns = criteriaQuery.getColumnsUsingProjection(
+ criteria, this.propertyName);
+ StringBuilder sql = new StringBuilder("SDO_WITHIN_DISTANCE(");
+ sql.append(columns[0]).append(",").append("?");
+ if (param != null && !param.isEmpty()) {
+ sql.append(",").append(param.toQuotedString());
+ }
+ sql.append(") = 'TRUE'");
+ return sql.toString();
+ }
+ };
+ }
+
+ public static Criterion SDOWithinDistance(String propertyName,
+ Geometry geom, Double distance, SDOParameterMap param) {
+ if (param == null) {
+ param = new SDOParameterMap();
+ }
+ param.setDistance(distance);
+ return SDOWithinDistance(propertyName, geom, param);
+ }
+}
+
+abstract class OracleSpatialCriterion implements Criterion {
+ protected String propertyName;
+
+ protected Geometry value;
+
+ protected SDOParameterMap param;
+
+ public OracleSpatialCriterion(String propertyName, Geometry value,
+ SDOParameterMap param) {
+ this.propertyName = propertyName;
+ this.value = value;
+ this.param = param;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.hibernate.criterion.Criterion#getTypedValues(org.hibernate.Criteria,
+ * org.hibernate.criterion.CriteriaQuery)
+ */
+
+ public TypedValue[] getTypedValues(Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ return new TypedValue[]{criteriaQuery.getTypedValue(criteria,
+ propertyName, value)};
+ }
+
+ abstract public String toSqlString(Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException;
+
+}
\ No newline at end of file
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/RelationshipMask.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/RelationshipMask.java
new file mode 100644
index 0000000000..77b0bdd811
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/RelationshipMask.java
@@ -0,0 +1,45 @@
+/**
+ * $Id: RelationshipMask.java 103 2008-08-15 10:45:29Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle.criterion;
+
+public enum RelationshipMask {
+ TOUCH, OVERLAPBYDISJOINT, OVERLAPBYINTERSECT, EQUAL, INSIDE, COVEREDBY, CONTAINS, COVERS, ANYINTERACT, ON;
+
+ public static String booleanCombination(RelationshipMask[] masks) {
+ String strMask = null;
+ for (RelationshipMask relationshipMask : masks) {
+ if (strMask == null) {
+ strMask = relationshipMask.toString();
+ } else {
+ strMask += "+" + relationshipMask.toString();
+ }
+ }
+ return strMask;
+ }
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/SDOParameterMap.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/SDOParameterMap.java
new file mode 100644
index 0000000000..97540537b8
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/criterion/SDOParameterMap.java
@@ -0,0 +1,192 @@
+/**
+ * $Id: SDOParameterMap.java 67 2007-12-16 16:41:55Z maesenka $
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007 Geovise BVBA
+ *
+ * This work was partially supported by the European Commission,
+ * under the 6th Framework Programme, contract IST-2-004688-STP.
+ *
+ * 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+package org.hibernate.spatial.dialect.oracle.criterion;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class represents the parameters that can be passed into Oracle's Spatial
+ * Operators
+ *
+ * @author Karel Maesen
+ *
+ */
+public class SDOParameterMap {
+
+ public static final String DISTANCE = "distance";
+
+ public static final String SDO_BATCH_SIZE = "sdo_batch_size";
+
+ public static final String SDO_NUM_RES = "sdo_num_res";
+
+ public static final String UNIT = "unit";
+
+ public static final String MIN_RESOLUTION = "min_resolution";
+
+ public static final String MAX_RESOLUTION = "max_resolution";
+
+ public static final String MASK = "mask";
+
+ public static final String QUERYTYPE = "querytype";
+
+ private Map params = new HashMap();
+
+ public SDOParameterMap() {
+ }
+
+ public boolean isEmpty() {
+ return this.params.isEmpty();
+ }
+
+ public void setDistance(Double distance) {
+ if (distance != null)
+ params.put(DISTANCE, distance);
+ }
+
+ public Double getDistance() {
+ return (Double) params.get(DISTANCE);
+ }
+
+ public void removeDistance() {
+ params.remove(DISTANCE);
+ }
+
+ public void setSdoBatchSize(Integer size) {
+ if (size != null)
+ params.put(SDO_BATCH_SIZE, size);
+ }
+
+ public Integer getSdoBatchSize() {
+ return (Integer) params.get(SDO_BATCH_SIZE);
+ }
+
+ public void removeSdoBatchSize() {
+ params.remove(SDO_BATCH_SIZE);
+ }
+
+ public void setSdoNumRes(Integer size) {
+ if (size != null)
+ params.put(SDO_NUM_RES, size);
+ }
+
+ public Integer getSdoNumRes() {
+ return (Integer) params.get(SDO_NUM_RES);
+ }
+
+ public void removeSdoNumRes() {
+ params.remove(SDO_NUM_RES);
+ }
+
+ public void setUnit(String unit) {
+ if (unit != null)
+ this.params.put(UNIT, unit);
+ }
+
+ public String getUnit() {
+ return (String) this.params.get(UNIT);
+ }
+
+ public void removeUnit() {
+ this.params.remove(UNIT);
+ }
+
+ public void setMaxResolution(Double res) {
+ if (res != null)
+ params.put(MAX_RESOLUTION, res);
+ }
+
+ public Double getMaxResolution() {
+ return (Double) params.get(MAX_RESOLUTION);
+ }
+
+ public void removeMaxResolution() {
+ params.remove(MAX_RESOLUTION);
+ }
+
+ public void setMinResolution(Double res) {
+ if (res != null)
+ params.put(MIN_RESOLUTION, res);
+ }
+
+ public Double getMinResolution() {
+ return (Double) params.get(MIN_RESOLUTION);
+ }
+
+ public void removeMinResolution() {
+ params.remove(MIN_RESOLUTION);
+ }
+
+ public void setMask(String mask) {
+ if (mask != null)
+ this.params.put(MASK, mask);
+ }
+
+ public String getMask() {
+ return (String) this.params.get(MASK);
+ }
+
+ public void removeMask() {
+ this.params.remove(MASK);
+ }
+
+ public void setQueryType(String queryType) {
+ if (queryType != null)
+ this.params.put(QUERYTYPE, queryType);
+ }
+
+ public void setQueryTypeToFilter() {
+ this.params.put(QUERYTYPE, "FILTER");
+ }
+
+ public String getQueryType() {
+ return (String) this.params.get(QUERYTYPE);
+ }
+
+ public void removeQueryType() {
+ this.params.remove(QUERYTYPE);
+ }
+
+ public String toQuotedString() {
+ StringBuilder stb = new StringBuilder();
+ if (params.isEmpty()) {
+ return "";
+ }
+ stb.append('\'');
+ for (String paramName : params.keySet()) {
+ if (params.get(paramName) == null)
+ continue;
+ stb.append(paramName).append("=").append(params.get(paramName))
+ .append(" ");
+ }
+ stb.deleteCharAt(stb.length() - 1);
+ stb.append('\'');
+ return stb.toString();
+ }
+
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueBinder.java
new file mode 100644
index 0000000000..424bdb01a4
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueBinder.java
@@ -0,0 +1,8 @@
+package org.hibernate.spatial.dialect.sqlserver;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: 8/23/11
+ */
+public class SqlServer2008GeometryValueBinder {
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java
new file mode 100644
index 0000000000..1342c54995
--- /dev/null
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java
@@ -0,0 +1,8 @@
+package org.hibernate.spatial.dialect.sqlserver;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: 8/23/11
+ */
+public class SqlServer2008GeometryValueExtractor {
+}
diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialIntegrator.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialIntegrator.java
index c2debdff3f..c74de81413 100644
--- a/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialIntegrator.java
+++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialIntegrator.java
@@ -3,6 +3,7 @@ package org.hibernate.spatial.integration;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.integrator.spi.Integrator;
+import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.spatial.GeometryType;
@@ -17,6 +18,11 @@ public class SpatialIntegrator implements Integrator {
sessionFactory.getTypeResolver().registerTypeOverride( GeometryType.INSTANCE );
}
+ @Override
+ public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
+ metadata.getTypeResolver().registerTypeOverride( GeometryType.INSTANCE );
+ }
+
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
//do nothing.
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/SpatialFunctionalTestCase.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/SpatialFunctionalTestCase.java
index 4c0458112d..f293e8db73 100644
--- a/hibernate-spatial/src/test/java/org/hibernate/spatial/SpatialFunctionalTestCase.java
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/SpatialFunctionalTestCase.java
@@ -91,7 +91,6 @@ public abstract class SpatialFunctionalTestCase extends BaseCoreFunctionalTestCa
}
public String getBaseForMappings() {
-// return "org/hibernatespatial/test/";
return "";
}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/TestSupportFactories.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/TestSupportFactories.java
index d54bb11640..358f3c6310 100644
--- a/hibernate-spatial/src/test/java/org/hibernate/spatial/TestSupportFactories.java
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/TestSupportFactories.java
@@ -56,9 +56,9 @@ public class TestSupportFactories {
// "org.hibernatespatial.mysql.MySQLSpatialInnoDBDialect".equals(canonicalName)) {
// return "org.hibernatespatial.mysql.MySQLTestSupport";
// }
-// if ("org.hibernatespatial.oracle.OracleSpatial10gDialect".equals(canonicalName)) {
-// return "org.hibernatespatial.oracle.OracleSDOTestSupport";
-// }
+ if ( "org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect".equals( canonicalName ) ) {
+ return "org.hibernate.spatial.dialect.oracle.OracleSDOTestSupport";
+ }
throw new IllegalArgumentException( "Dialect not known in test suite" );
}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/JDBCConnectionProxy.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/JDBCConnectionProxy.java
new file mode 100644
index 0000000000..6e59bca8ae
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/JDBCConnectionProxy.java
@@ -0,0 +1,234 @@
+package org.hibernatespatial.oracle;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * This class hides the actual Connection implementation class.
+ *
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Jun 30, 2010
+ */
+public class JDBCConnectionProxy implements Connection {
+
+ private final Connection delegate;
+
+ public JDBCConnectionProxy(Connection conn) {
+ this.delegate = conn;
+ }
+
+ public T unwrap(Class iface) throws SQLException {
+ return delegate.unwrap( iface );
+ }
+
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ return delegate.isWrapperFor( iface );
+ }
+
+ public Statement createStatement() throws SQLException {
+ return delegate.createStatement();
+ }
+
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return delegate.prepareStatement( sql );
+ }
+
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return delegate.prepareCall( sql );
+ }
+
+ public String nativeSQL(String sql) throws SQLException {
+ return delegate.nativeSQL( sql );
+ }
+
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ delegate.setAutoCommit( autoCommit );
+ }
+
+ public boolean getAutoCommit() throws SQLException {
+ return delegate.getAutoCommit();
+ }
+
+ public void commit() throws SQLException {
+ delegate.commit();
+ }
+
+ public void rollback() throws SQLException {
+ delegate.rollback();
+ }
+
+ public void close() throws SQLException {
+ delegate.close();
+ }
+
+ public boolean isClosed() throws SQLException {
+ return delegate.isClosed();
+ }
+
+ public DatabaseMetaData getMetaData() throws SQLException {
+ return delegate.getMetaData();
+ }
+
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ delegate.setReadOnly( readOnly );
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return delegate.isReadOnly();
+ }
+
+ public void setCatalog(String catalog) throws SQLException {
+ delegate.setCatalog( catalog );
+ }
+
+ public String getCatalog() throws SQLException {
+ return delegate.getCatalog();
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ delegate.setTransactionIsolation( level );
+ }
+
+ public int getTransactionIsolation() throws SQLException {
+ return delegate.getTransactionIsolation();
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return delegate.getWarnings();
+ }
+
+ public void clearWarnings() throws SQLException {
+ delegate.clearWarnings();
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ return delegate.createStatement( resultSetType, resultSetConcurrency );
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ return delegate.prepareStatement( sql, resultSetType, resultSetConcurrency );
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return delegate.prepareCall( sql, resultSetType, resultSetConcurrency );
+ }
+
+ public Map> getTypeMap() throws SQLException {
+ return delegate.getTypeMap();
+ }
+
+ public void setTypeMap(Map> map) throws SQLException {
+ delegate.setTypeMap( map );
+ }
+
+ public void setHoldability(int holdability) throws SQLException {
+ delegate.setHoldability( holdability );
+ }
+
+ public int getHoldability() throws SQLException {
+ return delegate.getHoldability();
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ return delegate.setSavepoint();
+ }
+
+ public Savepoint setSavepoint(String name) throws SQLException {
+ return delegate.setSavepoint( name );
+ }
+
+ public void rollback(Savepoint savepoint) throws SQLException {
+ delegate.rollback( savepoint );
+ }
+
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ delegate.releaseSavepoint( savepoint );
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return delegate.createStatement( resultSetType, resultSetConcurrency, resultSetHoldability );
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return delegate.prepareStatement( sql, resultSetType, resultSetConcurrency, resultSetHoldability );
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return delegate.prepareCall( sql, resultSetType, resultSetConcurrency, resultSetHoldability );
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ return delegate.prepareStatement( sql, autoGeneratedKeys );
+ }
+
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ return delegate.prepareStatement( sql, columnIndexes );
+ }
+
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ return delegate.prepareStatement( sql, columnNames );
+ }
+
+ public Clob createClob() throws SQLException {
+ return delegate.createClob();
+ }
+
+ public Blob createBlob() throws SQLException {
+ return delegate.createBlob();
+ }
+
+ public NClob createNClob() throws SQLException {
+ return delegate.createNClob();
+ }
+
+ public SQLXML createSQLXML() throws SQLException {
+ return delegate.createSQLXML();
+ }
+
+ public boolean isValid(int timeout) throws SQLException {
+ return delegate.isValid( timeout );
+ }
+
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ delegate.setClientInfo( name, value );
+ }
+
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ delegate.setClientInfo( properties );
+ }
+
+ public String getClientInfo(String name) throws SQLException {
+ return delegate.getClientInfo( name );
+ }
+
+ public Properties getClientInfo() throws SQLException {
+ return delegate.getClientInfo();
+ }
+
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ return delegate.createArrayOf( typeName, elements );
+ }
+
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ return delegate.createStruct( typeName, attributes );
+ }
+}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSDOTestSupport.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSDOTestSupport.java
new file mode 100644
index 0000000000..e9ded59fd0
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSDOTestSupport.java
@@ -0,0 +1,37 @@
+package org.hibernate.spatial.dialect.oracle;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.spatial.test.AbstractExpectationsFactory;
+import org.hibernate.spatial.test.DataSourceUtils;
+import org.hibernate.spatial.test.SQLExpressionTemplate;
+import org.hibernate.spatial.test.TestData;
+import org.hibernate.spatial.test.TestSupport;
+import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
+
+/**
+ * @author Karel Maesen, Geovise BVBA
+ * creation-date: Oct 22, 2010
+ */
+public class OracleSDOTestSupport extends TestSupport {
+
+ @Override
+ public TestData createTestData(BaseCoreFunctionalTestCase testcase) {
+ return TestData.fromFile( "test-sdo-geometry-data-set-2D.xml", new SDOTestDataReader() );
+ }
+
+ @Override
+ public AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) {
+ return new SDOGeometryExpectationsFactory( dataSourceUtils );
+ }
+
+ @Override
+ public SQLExpressionTemplate getSQLExpressionTemplate() {
+ return new SDOGeometryExpressionTemplate();
+ }
+
+ @Override
+ public DataSourceUtils createDataSourceUtil(Configuration configuration) {
+ this.configuration = configuration;
+ return new SDODataSourceUtils( driver(), url(), user(), passwd(), getSQLExpressionTemplate() );
+ }
+}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDODataSourceUtils.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDODataSourceUtils.java
new file mode 100644
index 0000000000..382415cd78
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDODataSourceUtils.java
@@ -0,0 +1,74 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import java.sql.SQLException;
+
+import org.hibernate.spatial.test.DataSourceUtils;
+import org.hibernate.spatial.test.SQLExpressionTemplate;
+
+
+public class SDODataSourceUtils extends DataSourceUtils {
+
+ public SDODataSourceUtils(String jdbcDriver, String jdbcUrl, String jdbcUser, String jdbcPass, SQLExpressionTemplate sqlExpressionTemplate) {
+ super( jdbcDriver, jdbcUrl, jdbcUser, jdbcPass, sqlExpressionTemplate );
+ }
+
+ @Override
+ public void afterCreateSchema() {
+ super.afterCreateSchema();
+ try {
+ setGeomMetaDataTo2D();
+ createIndex();
+ }
+ catch ( SQLException e ) {
+ throw new RuntimeException( e );
+ }
+
+ }
+
+ private void createIndex() throws SQLException {
+ String sql = "create index idx_spatial_geomtest on geomtest (geom) indextype is mdsys.spatial_index";
+ executeStatement( sql );
+ }
+
+ private void setGeomMetaDataTo2D() throws SQLException {
+ String sql1 = "delete from user_sdo_geom_metadata where TABLE_NAME = 'GEOMTEST'";
+ String sql2 = "insert into user_sdo_geom_metadata values (" +
+ " 'GEOMTEST'," +
+ " 'geom'," +
+ " SDO_DIM_ARRAY(" +
+ " SDO_DIM_ELEMENT('X', -180, 180, 0.00001)," +
+ " SDO_DIM_ELEMENT('Y', -90, 90, 0.00001)" +
+ " )," +
+ " 4326)";
+ executeStatement( sql1 );
+ executeStatement( sql2 );
+
+ }
+
+
+}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpectationsFactory.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpectationsFactory.java
new file mode 100644
index 0000000000..639ce98156
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpectationsFactory.java
@@ -0,0 +1,270 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.Point;
+
+import org.hibernate.spatial.test.AbstractExpectationsFactory;
+import org.hibernate.spatial.test.DataSourceUtils;
+import org.hibernate.spatial.test.NativeSQLStatement;
+
+/**
+ * Expectations factory for Oracle 10g (SDOGeometry).
+ *
+ * @Author Karel Maesen, Geovise BVBA
+ */
+public class SDOGeometryExpectationsFactory extends AbstractExpectationsFactory {
+
+ private final SDOGeometryValueExtractor decoder = new SDOGeometryValueExtractor();
+
+ public SDOGeometryExpectationsFactory(DataSourceUtils dataSourceUtils) {
+ super( dataSourceUtils );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Touch(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Touch(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Overlap(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Overlap(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Relate(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326), '" + matrix + "') from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Relate(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326), '" + matrix + "') = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Intersects(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Intersects(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeFilterStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, 1 from GEOMTEST t where SDO_FILTER(t.GEOM, MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326).GEOM) = 'TRUE' ",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Distance(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeDimensionSQL() {
+ return createNativeSQLStatement(
+ "select ID, MDSYS.OGC_DIMENSION(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM( T.GEOM)) FROM GEOMTEST T"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeBufferStatement(Double distance) {
+ return createNativeSQLStatement(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Buffer(?).GEOM from GEOMTEST T where t.GEOM.SDO_SRID = 4326",
+ new Double[] { distance }
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Union(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)).ST_ConvexHull().GEOM from GEOMTEST T where t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Intersection(MDSYS.ST_GEOMETRY.FROM_WKT(?,4326)).GEOM FROM GEOMTEST t where t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Difference(MDSYS.ST_GEOMETRY.FROM_WKT(?,4326)).GEOM FROM GEOMTEST t where t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_SymmetricDifference(MDSYS.ST_GEOMETRY.FROM_WKT(?,4326)).GEOM FROM GEOMTEST t where t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Union(MDSYS.ST_GEOMETRY.FROM_WKT(?,4326)).GEOM FROM GEOMTEST t where t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeAsTextStatement() {
+ return createNativeSQLStatement( "select t.ID, t.GEOM.GET_WKT() FROM GEOMTEST T" );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeSridStatement() {
+ return createNativeSQLStatement( "SELECT t.ID, t.GEOM.SDO_SRID FROM GEOMTEST t" );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeIsSimpleStatement() {
+ return createNativeSQLStatement(
+ "SELECT t.ID, MDSYS.OGC_ISSIMPLE(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM)) FROM GEOMTEST t where MDSYS.OGC_ISSIMPLE(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM)) = 1"
+ );
+
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeIsEmptyStatement() {
+ return createNativeSQLStatement(
+ "SELECT t.ID, MDSYS.OGC_ISEMPTY(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM)) FROM GEOMTEST t"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeIsNotEmptyStatement() {
+ return createNativeSQLStatement(
+ "SELECT t.ID, CASE MDSYS.OGC_ISEMPTY(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM)) WHEN 0 THEN 1 ELSE 0 END FROM GEOMTEST t"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeBoundaryStatement() {
+ return createNativeSQLStatement(
+ "SELECT t.ID, MDSYS.OGC_BOUNDARY(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM)).GEOM FROM GEOMTEST t"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeEnvelopeStatement() {
+ return createNativeSQLStatement(
+ "SELECT t.ID, MDSYS.OGC_ENVELOPE(MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM)).GEOM FROM GEOMTEST t"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeAsBinaryStatement() {
+ return createNativeSQLStatement( "select t.ID, t.GEOM.GET_WKB() FROM GEOMTEST T" );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeGeometryTypeStatement() {
+ return createNativeSQLStatement(
+ "select t.id, CASE t.geom.Get_GType() WHEN 1 THEN 'POINT' WHEN 2 THEN 'LINESTRING' WHEN 3 THEN 'POLYGON' WHEN 5 THEN 'MULTIPOINT' WHEN 6 THEN 'MULTILINE' WHEN 7 THEN 'MULTIPOLYGON' END from GEOMTEST t"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeWithinStatement(Geometry testPolygon) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, mdsys.OGC_WITHIN( MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM), MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where mdsys.OGC_WITHIN( MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM), MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ testPolygon.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeEqualsStatement(Geometry testPolygon) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Equals(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Equals(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ testPolygon.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Cross(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Cross(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeContainsStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Contains(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Contains(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) {
+ return createNativeSQLStatementAllWKTParams(
+ "select t.id, MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Disjoint(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) from GEOMTEST T where MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(t.GEOM).ST_Disjoint(MDSYS.ST_GEOMETRY.FROM_WKT(?, 4326)) = 1 and t.GEOM.SDO_SRID = 4326",
+ geom.toText()
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeTransformStatement(int epsg) {
+ return createNativeSQLStatement(
+ "select t.id, MDSYS.SDO_CS.transform(t.geom," + epsg + ") from GeomTest t where t.geom.SDO_SRID = 4326"
+ );
+ }
+
+ @Override
+ protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) {
+ return createNativeSQLStatement( "select t.id, 1 from GeomTest t where t.geom.SDO_SRID = " + srid );
+ }
+
+ @Override
+ protected Geometry decode(Object o) {
+ return decoder.toJTS( o );
+ }
+}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpressionTemplate.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpressionTemplate.java
new file mode 100644
index 0000000000..2604b37842
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOGeometryExpressionTemplate.java
@@ -0,0 +1,39 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import org.hibernate.spatial.test.SQLExpressionTemplate;
+import org.hibernate.spatial.test.TestDataElement;
+
+public class SDOGeometryExpressionTemplate implements SQLExpressionTemplate {
+
+ final String SQL_TEMPLATE = "insert into geomtest values (%d, '%s', %s)";
+
+ public String toInsertSql(TestDataElement testDataElement) {
+ SDOTestDataElement sdoTestDataElement = (SDOTestDataElement) testDataElement;
+ return String.format( SQL_TEMPLATE, sdoTestDataElement.id, sdoTestDataElement.type, sdoTestDataElement.sdo );
+ }
+}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataElement.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataElement.java
new file mode 100644
index 0000000000..dbead63dcb
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataElement.java
@@ -0,0 +1,47 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+
+import org.hibernate.spatial.test.TestDataElement;
+
+/**
+ * A specialised subclass for SDOGeometry test objects
+ *
+ * Oracle 10g WKT support is limited to 2D geometries, and there is
+ * no method of specifying SRID. That is why we here add the equivalent SDO expression
+ * that can be used by the TestData
+ */
+public class SDOTestDataElement extends TestDataElement {
+
+ public final String sdo;
+
+ public SDOTestDataElement(int id, String type, String wkt, int srid, String sdo) {
+ super( id, type, wkt, srid );
+ this.sdo = sdo;
+ }
+
+}
diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataReader.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataReader.java
new file mode 100644
index 0000000000..e0a4eabe62
--- /dev/null
+++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/SDOTestDataReader.java
@@ -0,0 +1,50 @@
+/*
+ * $Id:$
+ *
+ * This file is part of Hibernate Spatial, an extension to the
+ * hibernate ORM solution for geographic data.
+ *
+ * Copyright © 2007-2010 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
+ *
+ * For more information, visit: http://www.hibernatespatial.org/
+ */
+
+package org.hibernate.spatial.dialect.oracle;
+
+import java.util.List;
+
+import org.dom4j.Element;
+
+import org.hibernate.spatial.test.TestDataElement;
+import org.hibernate.spatial.test.TestDataReader;
+
+
+public class SDOTestDataReader extends TestDataReader {
+
+
+ @Override
+ protected void addDataElement(Element element, List testDataElements) {
+ int id = Integer.valueOf( element.selectSingleNode( "id" ).getText() );
+ String type = element.selectSingleNode( "type" ).getText();
+ String wkt = element.selectSingleNode( "wkt" ).getText();
+ int srid = Integer.valueOf( element.selectSingleNode( "srid" ).getText() );
+ String sdo = element.selectSingleNode( "sdo" ).getText();
+ TestDataElement testDataElement = new SDOTestDataElement( id, type, wkt, srid, sdo );
+ testDataElements.add( testDataElement );
+ }
+
+}
diff --git a/hibernate-spatial/src/test/resources/hibernate.properties b/hibernate-spatial/src/test/resources/hibernate.properties
index cd7f5dc5ea..732b4758fb 100644
--- a/hibernate-spatial/src/test/resources/hibernate.properties
+++ b/hibernate-spatial/src/test/resources/hibernate.properties
@@ -21,11 +21,19 @@
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301 USA
#
-hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisDialect
-hibernate.connection.driver_class org.postgresql.Driver
-hibernate.connection.url jdbc:postgresql://localhost:5432:hibbrtru
-hibernate.connection.username hibbrtru
-hibernate.connection.password hibbrtru
+
+#hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisDialect
+#hibernate.connection.driver_class org.postgresql.Driver
+#hibernate.connection.url jdbc:postgresql://localhost:5432:hibbrtru
+#hibernate.connection.username hibbrtru
+#hibernate.connection.password hibbrtru
+
+hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
+hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
+hibernate.connection.url jdbc:oracle:thin:@oracle.geovise.com/ORCL
+hibernate.connection.username hbs
+hibernate.connection.password hbs
+
hibernate.connection.pool_size 5
diff --git a/hibernate-spatial/src/test/resources/org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect.properties b/hibernate-spatial/src/test/resources/org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect.properties
new file mode 100644
index 0000000000..79b4a9acea
--- /dev/null
+++ b/hibernate-spatial/src/test/resources/org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect.properties
@@ -0,0 +1,27 @@
+#
+# $Id: org.hibernatespatial.oracle.OracleSpatial10gDialect.properties 268 2010-10-28 19:16:54Z maesenka $
+#
+# This file is part of Hibernate Spatial, an extension to the
+# hibernate ORM solution for geographic data.
+#
+# Copyright © 2007-2010 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
+#
+# For more information, visit: http://www.hibernatespatial.org/
+#
+
+OGC_STRICT=true
+CONNECTION-FINDER=org.hibernate.spatial.dialect.oracle.DefaultConnectionFinder
\ No newline at end of file
diff --git a/hibernate-spatial/src/test/resources/test-sdo-geometry-data-set-2D.xml b/hibernate-spatial/src/test/resources/test-sdo-geometry-data-set-2D.xml
new file mode 100644
index 0000000000..e10a59934c
--- /dev/null
+++ b/hibernate-spatial/src/test/resources/test-sdo-geometry-data-set-2D.xml
@@ -0,0 +1,282 @@
+
+
+
+
+
+
+ 1
+ POINT
+ SDO_GEOMETRY(2001, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(10.0, 5.0))
+ POINT(10 5)
+ 4326
+
+
+ 2
+ POINT
+ SDO_GEOMETRY(2001, 4326, SDO_POINT_TYPE(52.25, 2.53, NULL), NULL, NULL)
+ POINT(52.25 2.53)
+ 4326
+
+
+
+
+ 5
+ LINESTRING
+ LINESTRING(10.0 5.0, 20.0 15.0)
+ 4326
+ SDO_GEOMETRY(2002, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 20.0, 15.0))
+
+
+
+ 6
+ LINESTRING
+ LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)
+ 4326
+ SDO_GEOMETRY(2002, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 20.0, 15.0, 30.3,
+ 22.4, 10.0, 30.0 ))
+
+
+
+
+
+ 11
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))
+ 4326
+ SDO_GEOMETRY(2006, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1,5,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 20.0,
+ 15.0,25.0,30.0, 30.0,20.0))
+
+
+
+
+ 12
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0))
+
+ 4326
+ SDO_GEOMETRY(2006, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1,9,2,1),
+ SDO_ORDINATE_ARRAY(10.0,5.0,20.0,15.0,30.3,22.4,10,30.0,40.0,20.0,42.0,18.0,43.0,16.0,40,14.0))
+
+
+
+
+ 16
+ POLYGON
+ POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )
+ 4326
+ SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1),
+ SDO_ORDINATE_ARRAY(0,0,0,10,10,10,10,0,0,0))
+
+
+
+
+ 18
+ POLYGON
+ POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))
+ SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 11, 2003, 1), SDO_ORDINATE_ARRAY(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
+ SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1),
+ SDO_ORDINATE_ARRAY(110,110,110,120,120,120,120,110,110,110))
+
+
+
+
+ 20
+ MULTIPOLYGON
+ MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, 120 140, 130 134, 105 100)) )
+ 4326
+ SDO_GEOMETRY(2007, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 9, 1003, 1), SDO_ORDINATE_ARRAY(10, 20, 30,
+ 40, 44, 50, 10, 20, 105, 100, 120, 140, 130, 134, 105, 100))
+
+
+
+
+ 22
+ MULTIPOLYGON
+ MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 100, 120 140, 130
+ 134, 105 100)))
+
+ SDO_GEOMETRY(2007, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 11, 2003, 1, 21, 1003, 1),
+ SDO_ORDINATE_ARRAY(0, 0, 0, 50, 50, 50, 50, 0, 0, 0, 10, 10, 10, 20, 20, 20, 20, 10, 10, 10, 105, 100, 120,
+ 140, 130, 134, 105, 100))
+
+ 4326
+
+
+
+
+ 25
+ MULTIPOINT
+ MULTIPOINT(21 2, 25 5, 30 3)
+ 4326
+ SDO_GEOMETRY(2005, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(21,2,25,5,30,3))
+
+
+ 26
+ MULTIPOINT
+ MULTIPOINT(21 2)
+ 4326
+ SDO_GEOMETRY(2005, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(21,2))
+
+
+
+
+
+
+
+
+
+
diff --git a/hibernate-spatial/src/test/resources/test-sdo-geometry-data-set.xml b/hibernate-spatial/src/test/resources/test-sdo-geometry-data-set.xml
new file mode 100644
index 0000000000..92b5e3277b
--- /dev/null
+++ b/hibernate-spatial/src/test/resources/test-sdo-geometry-data-set.xml
@@ -0,0 +1,401 @@
+
+
+
+
+
+
+ 1
+ POINT
+ SDO_GEOMETRY(2001, 0, SDO_POINT_TYPE(10, 5, NULL), NULL, NULL)
+ POINT(10 5)
+ 4326
+
+
+ 2
+ POINT
+ SDO_GEOMETRY(2001, 4326, SDO_POINT_TYPE(52.25, 2.53, NULL), NULL, NULL)
+ POINT(52.25 2.53)
+ 4326
+
+
+
+ 3
+ POINT
+ SDO_GEOMETRY(3001, 31370, SDO_POINT_TYPE(150000, 200000, 500), NULL, NULL)
+ POINT(150000 200000 500)
+ 4326
+
+
+ 4
+ POINT
+ SDO_GEOMETRY(4401, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(10.0, 2.0, 1.0, 3.0))
+ POINT(10.0 2.0 1.0 3.0)
+ 4326
+
+
+
+ 5
+ LINESTRING
+ LINESTRING(10.0 5.0, 20.0 15.0)
+ 4326
+ SDO_GEOMETRY(2002, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 20.0, 15.0))
+
+
+
+ 6
+ LINESTRING
+ LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)
+ 4326
+ SDO_GEOMETRY(2002, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 20.0, 15.0, 30.3,
+ 22.4, 10.0, 30.0 ))
+
+
+
+
+ 7
+ LINESTRING
+ LINESTRING(10.0 5.0 0.0, 20.0 15.0 3.0)
+ SDO_GEOMETRY(3002, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 0.0, 20.0, 15, 3.0
+ ))
+
+ 4326
+
+
+
+ 8
+ LINESTRING
+ LINESTRING(10.0 5.0 0.0 0.0, 20.0 15.0 3.0 1.0)
+ 4326
+ SDO_GEOMETRY(4402, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 0.0, 0.0, 20.0,
+ 15, 3.0, 1.0))
+
+
+
+
+ 9
+ LINESTRING
+ LINESTRING(10.0 5.0 1, 20.0 15.0 2, 30.3 22.4 5, 10 30.0 2)
+ 4326
+ SDO_GEOMETRY(3002, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 1.0,20.0, 15, 2.0,
+ 30.3, 22.4, 5.0, 10.0, 30.0, 2.0))
+
+
+
+
+ 10
+ LINESTRING
+ LINESTRING(10.0 5.0 1 1, 20.0 15.0 2 3, 30.3 22.4 5 10, 10 30.0 2 12)
+ 4326
+ SDO_GEOMETRY(4402, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10.0,5.0,1,1, 20.0, 15.0, 2,
+ 3, 30.3, 22.4, 5, 10, 10, 30.0, 2, 12))
+
+
+
+
+ 11
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))
+ 4326
+ SDO_GEOMETRY(2006, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1,5,2,1), SDO_ORDINATE_ARRAY(10.0, 5.0, 20.0,
+ 15.0,25.0,30.0, 30.0,20.0))
+
+
+
+
+ 12
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0))
+
+ 4326
+ SDO_GEOMETRY(2006, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1,9,2,1),
+ SDO_ORDINATE_ARRAY(10.0,5.0,20.0,15.0,30.3,22.4,10,30.0,40.0,20.0,42.0,18.0,43.0,16.0,40,14.0))
+
+
+
+
+ 13
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0 1.0, 20.0 15.0 2.0, 30.3 22.4 1.0, 10 30.0 1.0),(40.0 20.0 0.0, 42.0 18.0 1.0,
+ 43.0 16.0 2.0, 40 14.0 3.0))
+
+ 4326
+ SDO_GEOMETRY(3006, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1,13,2,1),
+ SDO_ORDINATE_ARRAY(10.0,5.0,1.0,20.0,15.0,2.0,30.3,22.4,1.0,10,30.0,1.0,40.0,20.0,0.0,42.0,18.0,1.0,43.0,16.0,2.0,40,14.0,3.0))
+
+
+
+
+ 14
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0),(40.0 20.0 0.0
+ 3.0, 42.0 18.0 1.0 4.0, 43.0 16.0 2.0 5.0, 40 14.0 3.0 6.0))
+
+ 4326
+ SDO_GEOMETRY(4406, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1,17,2,1),
+ SDO_ORDINATE_ARRAY(10.0,5.0,1.0,0.0,20.0,15.0,2.0,0.0,30.3,22.4,1.0,1.0,10,30.0,1.0,2.0,40.0,20.0,0.0,3.0,42.0,18.0,1.0,4.0,43.0,16.0,2.0,5.0,40,14.0,3.0,6.0))
+
+
+
+
+ 15
+ MULTILINESTRING
+ MULTILINESTRING((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0))
+ 4326
+ SDO_GEOMETRY(4406, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,2,1),
+ SDO_ORDINATE_ARRAY(10.0,5.0,1.0,0.0,20.0,15.0,2.0,0.0,30.3,22.4,1.0,1.0,10,30.0,1.0,2.0))
+
+
+
+
+
+ 16
+ POLYGON
+ POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )
+ 4326
+ SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1),
+ SDO_ORDINATE_ARRAY(0,0,0,10,10,10,10,0,0,0))
+
+
+
+
+
+ 17
+ POLYGON
+ POLYGON( (0 0 0, 0 10 1, 10 10 1, 10 0 1, 0 0 0) )
+ 4326
+ SDO_GEOMETRY(3003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1),
+ SDO_ORDINATE_ARRAY(0,0,0,0,10,1,10,10,1,10,0,1,0,0,0))
+
+
+
+ 18
+ POLYGON
+ POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))
+ SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 11, 2003, 1), SDO_ORDINATE_ARRAY(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
+ SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1),
+ SDO_ORDINATE_ARRAY(110,110,110,120,120,120,120,110,110,110))
+
+
+
+
+ 20
+ MULTIPOLYGON
+ MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, 120 140, 130 134, 105 100)) )
+ 4326
+ SDO_GEOMETRY(2007, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 9, 1003, 1), SDO_ORDINATE_ARRAY(10, 20, 30,
+ 40, 44, 50, 10, 20, 105, 100, 120, 140, 130, 134, 105, 100))
+
+
+
+ 21
+ MULTIPOLYGON
+ MULTIPOLYGON( ((10 20 1, 30 40 2, 44 50 2, 10 20 1)), ((105 100 0, 120 140 10, 130 134 20, 105 100 0)) )
+
+ 4326
+ SDO_GEOMETRY(3007, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 13, 1003, 1),
+ SDO_ORDINATE_ARRAY(10,20,1,30,40,2,44,50,2,10,20,1,105,100,0,120,140,10,130,134,20,105,100,0))
+
+
+
+ 22
+ MULTIPOLYGON
+ MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 100, 120 140, 130
+ 134, 105 100)))
+
+ SDO_GEOMETRY(2007, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 11, 2003, 1, 21, 1003, 1),
+ SDO_ORDINATE_ARRAY(0, 0, 0, 50, 50, 50, 50, 0, 0, 0, 10, 10, 10, 20, 20, 20, 20, 10, 10, 10, 105, 100, 120,
+ 140, 130, 134, 105, 100))
+
+ 4326
+
+
+
+
+ 25
+ MULTIPOINT
+ MULTIPOINT(21 2, 25 5, 30 3)
+ 4326
+ SDO_GEOMETRY(2005, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(21,2,25,5,30,3))
+
+
+ 26
+ MULTIPOINT
+ MULTIPOINT(21 2)
+ 4326
+ SDO_GEOMETRY(2005, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(21,2))
+
+
+ 27
+ MULTIPOINT
+ MULTIPOINT(21 2 1, 25 5 2, 30 3 5)
+ 4326
+ SDO_GEOMETRY(3005, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1), SDO_ORDINATE_ARRAY(21,2,1,25,5,2,30,3,5))
+
+
+ 28
+ MULTIPOINT
+ MULTIPOINT(21 2 1 0, 25 5 2 4, 30 3 5 2)
+ 4326
+ SDO_GEOMETRY(4405, 4326, NULL, SDO_ELEM_INFO_ARRAY(1,1,1),
+ SDO_ORDINATE_ARRAY(21,2,1,0,25,5,2,4,30,3,5,2))
+
+
+
+
+
+
+
+
+
+