/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.h2geodb;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.type.StandardBasicTypes;
/**
* Extends the H2Dialect by also including information on spatial functions.
*
* @author Jan Boonen, Geodan IT b.v.
*/
public class GeoDBDialect extends H2Dialect implements SpatialDialect {
/**
* Constructor. Registers OGC simple feature functions (see
* http://portal.opengeospatial.org/files/?artifact_id=829 for details).
* <p/>
* Note for the registerfunction method: it registers non-standard database
* functions: first argument is the internal (OGC standard) function name,
* second the name as it occurs in the spatial dialect
*/
public GeoDBDialect() {
super();
// Register Geometry column type
registerColumnType( GeoDBGeometryTypeDescriptor.INSTANCE.getSqlType(), "GEOMETRY" );
// Register functions that operate on spatial types
registerFunction( "dimension", new StandardSQLFunction( "ST_Dimension", StandardBasicTypes.INTEGER ) );
registerFunction( "geometrytype", new StandardSQLFunction( "GeometryType", StandardBasicTypes.STRING ) );
registerFunction( "srid", new StandardSQLFunction( "ST_SRID", StandardBasicTypes.INTEGER ) );
registerFunction( "envelope", new StandardSQLFunction( "ST_Envelope" ) );
registerFunction( "astext", new StandardSQLFunction( "ST_AsText", StandardBasicTypes.STRING ) );
registerFunction( "asbinary", new StandardSQLFunction( "ST_AsEWKB", StandardBasicTypes.BINARY ) );
registerFunction( "isempty", new StandardSQLFunction( "ST_IsEmpty", StandardBasicTypes.BOOLEAN ) );
registerFunction( "issimple", new StandardSQLFunction( "ST_IsSimple", StandardBasicTypes.BOOLEAN ) );
registerFunction( "boundary", new StandardSQLFunction( "ST_Boundary" ) );
// Register functions for spatial relation constructs
registerFunction( "overlaps", new StandardSQLFunction( "ST_Overlaps", StandardBasicTypes.BOOLEAN ) );
registerFunction( "intersects", new StandardSQLFunction( "ST_Intersects", StandardBasicTypes.BOOLEAN ) );
registerFunction( "equals", new StandardSQLFunction( "ST_Equals", StandardBasicTypes.BOOLEAN ) );
registerFunction( "contains", new StandardSQLFunction( "ST_Contains", StandardBasicTypes.BOOLEAN ) );
registerFunction( "crosses", new StandardSQLFunction( "ST_Crosses", StandardBasicTypes.BOOLEAN ) );
registerFunction( "disjoint", new StandardSQLFunction( "ST_Disjoint", StandardBasicTypes.BOOLEAN ) );
registerFunction( "touches", new StandardSQLFunction( "ST_Touches", StandardBasicTypes.BOOLEAN ) );
registerFunction( "within", new StandardSQLFunction( "ST_Within", StandardBasicTypes.BOOLEAN ) );
registerFunction( "relate", new StandardSQLFunction( "ST_Relate", StandardBasicTypes.BOOLEAN ) );
// register the spatial analysis functions
registerFunction( "distance", new StandardSQLFunction( "ST_Distance", StandardBasicTypes.DOUBLE ) );
registerFunction( "buffer", new StandardSQLFunction( "ST_Buffer" ) );
registerFunction( "convexhull", new StandardSQLFunction( "ST_ConvexHull" ) );
registerFunction( "difference", new StandardSQLFunction( "ST_Difference" ) );
registerFunction( "intersection", new StandardSQLFunction( "ST_Intersection" ) );
registerFunction( "symdifference", new StandardSQLFunction( "ST_SymDifference" ) );
registerFunction( "geomunion", new StandardSQLFunction( "ST_Union" ) );
registerFunction( "dwithin", new StandardSQLFunction( "ST_DWithin", StandardBasicTypes.BOOLEAN ) );
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
typeContributions.contributeType( new GeolatteGeometryType( GeoDBGeometryTypeDescriptor.INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( GeoDBGeometryTypeDescriptor.INSTANCE ) );
}
@Override
public String getSpatialAggregateSQL(String columnName, int aggregation) {
switch ( aggregation ) {
// NOT YET AVAILABLE IN GEODB
// case SpatialAggregate.EXTENT:
// StringBuilder stbuf = new StringBuilder();
// stbuf.append("extent(").append(columnName).append(")");
// return stbuf.toString();
default:
throw new IllegalArgumentException(
"Aggregations of type " + aggregation + " are not supported by " +
"this dialect"
);
}
}
@Override
public String getDWithinSQL(String columnName) {
return "ST_DWithin(" + columnName + ",?,?)";
}
@Override
public String getHavingSridSQL(String columnName) {
return "( ST_srid(" + columnName + ") = ?)";
}
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
final String emptyExpr = " ST_IsEmpty(" + columnName + ") ";
return isEmpty ? emptyExpr : "( NOT " + emptyExpr + ")";
}
@Override
public String getSpatialFilterExpression(String columnName) {
return "(" + columnName + " && ? ) ";
}
@Override
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
switch ( spatialRelation ) {
case SpatialRelation.WITHIN:
return " ST_Within(" + columnName + ", ?)";
case SpatialRelation.CONTAINS:
return " ST_Contains(" + columnName + ", ?)";
case SpatialRelation.CROSSES:
return " ST_Crosses(" + columnName + ", ?)";
case SpatialRelation.OVERLAPS:
return " ST_Overlaps(" + columnName + ", ?)";
case SpatialRelation.DISJOINT:
return " ST_Disjoint(" + columnName + ", ?)";
case SpatialRelation.INTERSECTS:
return " ST_Intersects(" + columnName + ", ?)";
case SpatialRelation.TOUCHES:
return " ST_Touches(" + columnName + ", ?)";
case SpatialRelation.EQUALS:
return " ST_Equals(" + columnName + ", ?)";
default:
throw new IllegalArgumentException( "Spatial relation is not known by this dialect" );
}
}
@Override
public boolean supportsFiltering() {
return false;
}
@Override
public boolean supports(SpatialFunction function) {
return function != SpatialFunction.difference && (getFunctions().get( function.toString() ) != null);
}
}