HHH-13799 : Criteria API support for Hibernate Spatial (#3159)
* HHH-13799 : Criteria API support for Hibernate Spatial Co-authored-by: Karel Maesen <karel@geovise.com>
This commit is contained in:
parent
b914b02dca
commit
cab651e194
|
@ -10,7 +10,7 @@ hibernate.dialect org.hibernate.spatial.dialect.db2.DB2SpatialDialect
|
|||
hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver
|
||||
hibernate.connection.url jdbc:db2://localhost:50000/hibern8
|
||||
hibernate.connection.username db2inst1
|
||||
hibernate.connection.password password
|
||||
hibernate.connection.password oPucroAsMAgL
|
||||
|
||||
|
||||
hibernate.connection.pool_size 5
|
||||
|
|
|
@ -9,7 +9,7 @@ hibernate.dialect org.hibernate.spatial.dialect.sqlserver.SqlServer2012SpatialDi
|
|||
hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
hibernate.connection.url jdbc:sqlserver://localhost:1433;databaseName=TestDb
|
||||
hibernate.connection.username hibern8
|
||||
hibernate.connection.password hibern8Pass
|
||||
hibernate.connection.password langpaswoord123A%1
|
||||
|
||||
|
||||
hibernate.connection.pool_size 5
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#! /bin/bash
|
||||
|
||||
## The same effect can be achieved by setting the system properties
|
||||
# in ~/.gradle/gradle.properties
|
||||
|
||||
TASK=matrix
|
||||
if [[ -n $@ ]]; then
|
||||
TASK="$@"
|
||||
|
|
|
@ -164,8 +164,16 @@ public enum SpatialFunction {
|
|||
/**
|
||||
* the extents function
|
||||
*/
|
||||
extent( "common" );
|
||||
extent( "common" ),
|
||||
|
||||
/**
|
||||
* The filter function
|
||||
* <p>
|
||||
* <p>Corresponds to the Oracle Spatial's "SDO_FILTER" function, or the "&&" operator of PostGIS.
|
||||
*/
|
||||
filter( "filter" ),
|
||||
|
||||
;
|
||||
|
||||
private final String description;
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* An Interface for {@code SpatialDialect}s that require a custom
|
||||
* rendering to JPAQL for the filter predicate
|
||||
* <p>
|
||||
* Created by Karel Maesen, Geovise BVBA on 09/02/2020.
|
||||
*/
|
||||
public interface WithCustomJPAFilter {
|
||||
|
||||
String filterExpression(String geometryParam, String filterParam);
|
||||
}
|
|
@ -7,9 +7,15 @@
|
|||
|
||||
package org.hibernate.spatial.dialect.h2geodb;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
|
||||
import org.hibernate.spatial.GeolatteGeometryType;
|
||||
|
@ -19,6 +25,7 @@ import org.hibernate.spatial.SpatialDialect;
|
|||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.SpatialRelation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Extends the H2Dialect by also including information on spatial functions.
|
||||
|
@ -74,6 +81,8 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect {
|
|||
|
||||
registerFunction( "dwithin", new StandardSQLFunction( "ST_DWithin", StandardBasicTypes.BOOLEAN ) );
|
||||
|
||||
// Register Spatial Filter function
|
||||
registerFunction( SpatialFunction.filter.name(), new FilterFunction() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -157,4 +166,26 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect {
|
|||
return function != SpatialFunction.difference && ( getFunctions().get( function.toString() ) != null );
|
||||
}
|
||||
|
||||
private static class FilterFunction extends StandardSQLFunction {
|
||||
|
||||
public FilterFunction() {
|
||||
super( "&&" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(
|
||||
Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
|
||||
int argumentCount = arguments.size();
|
||||
if ( argumentCount != 2 ) {
|
||||
throw new QueryException( String.format( "2 arguments expected, received %d", argumentCount ) );
|
||||
}
|
||||
|
||||
return Stream.of(
|
||||
String.valueOf( arguments.get( 0 ) ),
|
||||
getRenderedName( arguments ),
|
||||
String.valueOf( arguments.get( 1 ) )
|
||||
).collect( Collectors.joining( " ", "(", ")" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
package org.hibernate.spatial.dialect.hana;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
import org.hibernate.dialect.HANAColumnStoreDialect;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService.Converter;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
|
||||
import org.hibernate.spatial.GeolatteGeometryType;
|
||||
|
@ -22,6 +24,7 @@ import org.hibernate.spatial.SpatialDialect;
|
|||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.SpatialRelation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
public class HANASpatialDialect extends HANAColumnStoreDialect implements SpatialDialect {
|
||||
|
||||
|
@ -102,6 +105,9 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
|
|||
registerFunction(
|
||||
SpatialFunction.within.name(),
|
||||
new HANASpatialFunction( "ST_Within", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
|
||||
registerFunction(
|
||||
SpatialFunction.filter.name(),
|
||||
new FilterFunction() );
|
||||
|
||||
/*
|
||||
* Additional HANA functions
|
||||
|
@ -408,4 +414,17 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class FilterFunction extends HANASpatialFunction {
|
||||
|
||||
public FilterFunction() {
|
||||
super( "ST_IntersectsFilter", StandardBasicTypes.NUMERIC_BOOLEAN, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(
|
||||
Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
|
||||
return super.render( firstArgumentType, arguments, sessionFactory ) + " = 1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.spatial.dialect.mysql;
|
||||
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
|
@ -163,6 +164,13 @@ class MySQL5SpatialFunctions extends SpatialFunctionsRegistry {
|
|||
// "union"
|
||||
// )
|
||||
// );
|
||||
|
||||
functionMap.put(
|
||||
SpatialFunction.filter.name(), new StandardSQLFunction(
|
||||
"MBRIntersects",
|
||||
StandardBasicTypes.BOOLEAN
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.spatial.dialect.mysql;
|
||||
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
|
@ -169,6 +170,13 @@ class MySQL8SpatialFunctions extends SpatialFunctionsRegistry {
|
|||
"ST_Union"
|
||||
)
|
||||
);
|
||||
|
||||
functionMap.put(
|
||||
SpatialFunction.filter.name(), new StandardSQLFunction(
|
||||
"MBRIntersects",
|
||||
StandardBasicTypes.BOOLEAN
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.spatial.dialect.oracle;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.spatial.SpatialDialect;
|
|||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.SpatialRelation;
|
||||
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
|
||||
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -33,7 +35,7 @@ import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
|
|||
* <p>
|
||||
* Created by Karel Maesen, Geovise BVBA on 01/11/16.
|
||||
*/
|
||||
class OracleSDOSupport implements SpatialDialect, Serializable {
|
||||
class OracleSDOSupport implements SpatialDialect, Serializable, WithCustomJPAFilter {
|
||||
|
||||
private static final HSMessageLogger log = Logger.getMessageLogger(
|
||||
HSMessageLogger.class,
|
||||
|
@ -290,7 +292,7 @@ class OracleSDOSupport implements SpatialDialect, Serializable {
|
|||
*/
|
||||
@Override
|
||||
public String getHavingSridSQL(String columnName) {
|
||||
return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName );
|
||||
return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName , Locale.US);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -304,7 +306,7 @@ class OracleSDOSupport implements SpatialDialect, Serializable {
|
|||
*/
|
||||
@Override
|
||||
public String getIsEmptySQL(String columnName, boolean isEmpty) {
|
||||
return String.format( "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )", columnName, isEmpty ? 1 : 0 );
|
||||
return String.format( "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )", columnName, isEmpty ? 1 : 0 , Locale.US);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,4 +333,8 @@ class OracleSDOSupport implements SpatialDialect, Serializable {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String filterExpression(String geometryParam, String filterParam) {
|
||||
return SpatialFunction.filter.name() + "(" + geometryParam + ", " + filterParam + ") = 'TRUE' ";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.service.ServiceRegistry;
|
|||
import org.hibernate.spatial.HSMessageLogger;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -26,7 +27,7 @@ import org.jboss.logging.Logger;
|
|||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
|
||||
public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, WithCustomJPAFilter, Serializable {
|
||||
|
||||
private static final HSMessageLogger log = Logger.getMessageLogger(
|
||||
HSMessageLogger.class,
|
||||
|
@ -101,5 +102,8 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements Spatial
|
|||
return ( getFunctions().get( function.toString() ) != null );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String filterExpression(String geometryParam, String filterParam) {
|
||||
return sdoSupport.filterExpression( geometryParam, filterParam );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.QueryException;
|
|||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.spatial.SpatialAnalysis;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.SpatialRelation;
|
||||
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
|
||||
import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate;
|
||||
|
@ -138,6 +139,12 @@ class OracleSpatialFunctions extends SpatialFunctionsRegistry {
|
|||
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.EXTENT, sdoSupport )
|
||||
);
|
||||
|
||||
// spatial filter function
|
||||
put(
|
||||
SpatialFunction.filter.name(),
|
||||
new StandardSQLFunction( "SDO_FILTER" )
|
||||
);
|
||||
|
||||
//other common functions
|
||||
|
||||
put( "transform", new StandardSQLFunction( "SDO_CS.TRANSFORM" ) );
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.service.ServiceRegistry;
|
|||
import org.hibernate.spatial.HSMessageLogger;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -25,7 +26,8 @@ import org.jboss.logging.Logger;
|
|||
* <p>
|
||||
* Created by Karel Maesen, Geovise BVBA on 11/02/17.
|
||||
*/
|
||||
public class OracleSpatialSDO10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
|
||||
public class OracleSpatialSDO10gDialect extends Oracle10gDialect
|
||||
implements SpatialDialect, WithCustomJPAFilter, Serializable {
|
||||
|
||||
private static final HSMessageLogger log = Logger.getMessageLogger(
|
||||
HSMessageLogger.class,
|
||||
|
@ -100,5 +102,8 @@ public class OracleSpatialSDO10gDialect extends Oracle10gDialect implements Spat
|
|||
return !function.equals( SpatialFunction.crosses ) && ( getFunctions().get( function.toString() ) != null );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String filterExpression(String geometryParam, String filterParam) {
|
||||
return sdoSupport.filterExpression( geometryParam, filterParam );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -177,6 +181,11 @@ class PostgisFunctions extends SpatialFunctionsRegistry {
|
|||
"extent", new ExtentFunction()
|
||||
);
|
||||
|
||||
//register Spatial Filter function
|
||||
put(
|
||||
SpatialFunction.filter.name(), new FilterFunction()
|
||||
);
|
||||
|
||||
//other common functions
|
||||
put(
|
||||
"dwithin", new StandardSQLFunction(
|
||||
|
@ -206,4 +215,26 @@ class PostgisFunctions extends SpatialFunctionsRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
private static class FilterFunction extends StandardSQLFunction {
|
||||
|
||||
public FilterFunction() {
|
||||
super( "&&" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(
|
||||
Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
|
||||
int argumentCount = arguments.size();
|
||||
if ( argumentCount != 2 ) {
|
||||
throw new QueryException( String.format( "2 arguments expected, received %d", argumentCount ) );
|
||||
}
|
||||
|
||||
return Stream.of(
|
||||
String.valueOf( arguments.get( 0 ) ),
|
||||
getRenderedName( arguments ),
|
||||
String.valueOf( arguments.get( 1 ) )
|
||||
).collect( Collectors.joining( " ", "(", ")" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.spatial.dialect.sqlserver;
|
||||
|
||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
|
@ -62,5 +63,7 @@ class SqlServerFunctions extends SpatialFunctionsRegistry {
|
|||
"pointonsurface", new SqlServerMethod( "STPointOnSurface" )
|
||||
);
|
||||
|
||||
// Register spatial filter function.
|
||||
put( SpatialFunction.filter.name(), new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.Filter(?2)" ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.predicate;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
|
||||
import org.hibernate.query.criteria.internal.ParameterRegistry;
|
||||
import org.hibernate.query.criteria.internal.Renderable;
|
||||
import org.hibernate.query.criteria.internal.compile.RenderingContext;
|
||||
import org.hibernate.query.criteria.internal.predicate.AbstractSimplePredicate;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.criterion.SpatialFilter;
|
||||
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
|
||||
import org.hibernate.spatial.jts.EnvelopeAdapter;
|
||||
|
||||
import org.locationtech.jts.geom.Envelope;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* JPA Criteria API {@link Predicate} equivalent of {@link SpatialFilter}.
|
||||
*/
|
||||
public class FilterPredicate extends AbstractSimplePredicate implements Serializable {
|
||||
|
||||
private final Expression<? extends Geometry> geometry;
|
||||
private final Expression<? extends Geometry> filter;
|
||||
|
||||
public FilterPredicate(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
|
||||
Expression<? extends Geometry> filter) {
|
||||
super( (CriteriaBuilderImpl) criteriaBuilder );
|
||||
this.geometry = geometry;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public FilterPredicate(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
|
||||
Geometry filter) {
|
||||
this( criteriaBuilder, geometry, criteriaBuilder.literal( filter )
|
||||
);
|
||||
}
|
||||
|
||||
public FilterPredicate(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
|
||||
Envelope envelope, int srid) {
|
||||
this( criteriaBuilder, geometry, EnvelopeAdapter.toPolygon( envelope, srid )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerParameters(ParameterRegistry registry) {
|
||||
Helper.possibleParameter( geometry, registry );
|
||||
Helper.possibleParameter( filter, registry );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(boolean isNegated, RenderingContext renderingContext) {
|
||||
String geometryParameter = ( (Renderable) geometry ).render( renderingContext );
|
||||
String filterParameter = ( (Renderable) filter ).render( renderingContext );
|
||||
Dialect dialect = renderingContext.getDialect();
|
||||
if ( !( dialect instanceof SpatialDialect ) ) {
|
||||
throw new IllegalStateException( "Dialect must be spatially enabled dialect" );
|
||||
}
|
||||
if ( dialect instanceof WithCustomJPAFilter ) {
|
||||
return ( (WithCustomJPAFilter) dialect ).filterExpression( geometryParameter, filterParameter );
|
||||
}
|
||||
else {
|
||||
return SpatialFunction.filter.name() + "(" + geometryParameter + ", " + filterParameter + ") = true";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,575 @@
|
|||
/*
|
||||
* 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.predicate;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.criterion.SpatialRestrictions;
|
||||
|
||||
import org.locationtech.jts.geom.Envelope;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
import org.locationtech.jts.geom.Polygon;
|
||||
|
||||
/**
|
||||
* A factory for spatial JPA Criteria API {@link Predicate}s.
|
||||
*
|
||||
* @author Daniel Shuy
|
||||
* @see SpatialRestrictions
|
||||
*/
|
||||
public final class SpatialPredicates {
|
||||
|
||||
private SpatialPredicates() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially equal" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially equal" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#eq(String, Geometry)
|
||||
*/
|
||||
public static Predicate eq(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.equals.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially equal" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially equal" predicate
|
||||
*
|
||||
* @see #eq(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate eq(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return eq( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially within" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially within" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#within(String, Geometry)
|
||||
*/
|
||||
public static Predicate within(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.within.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially within" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially within" predicate
|
||||
*
|
||||
* @see #within(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate within(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return within( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially contains" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially contains" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#contains(String, Geometry)
|
||||
*/
|
||||
public static Predicate contains(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.contains.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially contains" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially contains" predicate
|
||||
*
|
||||
* @see #contains(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate contains(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return contains( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially crosses" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially crosses" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#crosses(String, Geometry)
|
||||
*/
|
||||
public static Predicate crosses(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.crosses.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially crosses" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially crosses" predicate
|
||||
*
|
||||
* @see #crosses(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate crosses(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return crosses( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially disjoint" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially disjoint" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#disjoint(String, Geometry)
|
||||
*/
|
||||
public static Predicate disjoint(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.disjoint.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially disjoint" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially disjoint" predicate
|
||||
*
|
||||
* @see #disjoint(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate disjoint(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return disjoint( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially intersects" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially intersects" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#intersects(String, Geometry)
|
||||
*/
|
||||
public static Predicate intersects(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.intersects.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially intersects" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially intersects" predicate
|
||||
*
|
||||
* @see #intersects(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate intersects(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return intersects( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially overlaps" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially overlaps" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#overlaps(String, Geometry)
|
||||
*/
|
||||
public static Predicate overlaps(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.overlaps.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially overlaps" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially overlaps" predicate
|
||||
*
|
||||
* @see #overlaps(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate overlaps(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return overlaps( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially touches" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
*
|
||||
* @return "spatially touches" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#touches(String, Geometry)
|
||||
*/
|
||||
public static Predicate touches(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.touches.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "spatially touches" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
*
|
||||
* @return "spatially touches" predicate
|
||||
*
|
||||
* @see #touches(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate touches(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return touches( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for bounding box overlap constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression whose bounding box to use in the comparison
|
||||
*
|
||||
* @return bounding box overlap predicate
|
||||
*
|
||||
* @see FilterPredicate
|
||||
* @see SpatialRestrictions#filter(String, Geometry)
|
||||
*/
|
||||
public static Predicate filter(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2) {
|
||||
return new FilterPredicate( criteriaBuilder, geometry1, geometry2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for bounding box overlap constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value whose bounding box to use in the comparison
|
||||
*
|
||||
* @return bounding box overlap predicate
|
||||
*
|
||||
* @see FilterPredicate
|
||||
* @see SpatialRestrictions#filter(String, Geometry)
|
||||
*/
|
||||
public static Predicate filter(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return new FilterPredicate( criteriaBuilder, geometry1, geometry2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for bounding box overlap constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry geometry expression
|
||||
* @param envelope envelope or bounding box to use in the comparison
|
||||
* @param srid the SRID of the bounding box
|
||||
*
|
||||
* @return bounding box overlap predicate
|
||||
*
|
||||
* @see FilterPredicate
|
||||
* @see SpatialRestrictions#filter(String, Envelope, int)
|
||||
*/
|
||||
public static Predicate filterByPolygon(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
|
||||
Envelope envelope, int srid) {
|
||||
return new FilterPredicate( criteriaBuilder, geometry, envelope, srid );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "distance within" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
* @param distance distance expression
|
||||
*
|
||||
* @return "distance within" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#distanceWithin(String, Geometry, double)
|
||||
*/
|
||||
public static Predicate distanceWithin(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2, Expression<Double> distance) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.dwithin.toString(), boolean.class,
|
||||
geometry1, geometry2, distance
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "distance within" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
* @param distance distance expression
|
||||
*
|
||||
* @return "distance within" predicate
|
||||
*
|
||||
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
|
||||
*/
|
||||
public static Predicate distanceWithin(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2, Expression<Double> distance) {
|
||||
return distanceWithin( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 ), distance
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "distance within" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry value
|
||||
* @param distance distance value
|
||||
*
|
||||
* @return "distance within" predicate
|
||||
*
|
||||
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
|
||||
*/
|
||||
public static Predicate distanceWithin(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2, double distance) {
|
||||
return distanceWithin( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 ), criteriaBuilder.literal( distance )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "distance within" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry1 geometry expression
|
||||
* @param geometry2 geometry expression
|
||||
* @param distance distance value
|
||||
*
|
||||
* @return "distance within" predicate
|
||||
*
|
||||
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
|
||||
*/
|
||||
public static Predicate distanceWithin(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Expression<? extends Geometry> geometry2, double distance) {
|
||||
return distanceWithin( criteriaBuilder, geometry1, geometry2,
|
||||
criteriaBuilder.literal( distance )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "having srid" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry geometry expression
|
||||
* @param srid SRID expression
|
||||
*
|
||||
* @return "having srid" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#havingSRID(String, int)
|
||||
*/
|
||||
public static Predicate havingSRID(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
|
||||
Expression<Integer> srid) {
|
||||
return criteriaBuilder.equal(
|
||||
criteriaBuilder.function( SpatialFunction.srid.toString(), int.class, geometry ),
|
||||
srid
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "having srid" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry geometry expression
|
||||
* @param srid SRID expression
|
||||
*
|
||||
* @return "having srid" predicate
|
||||
*
|
||||
* @see #havingSRID(CriteriaBuilder, Expression, Expression)
|
||||
*/
|
||||
public static Predicate havingSRID(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
|
||||
int srid) {
|
||||
return havingSRID( criteriaBuilder, geometry,
|
||||
criteriaBuilder.literal( srid )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "is empty" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry geometry expression
|
||||
*
|
||||
* @return "is empty" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#isEmpty(String)
|
||||
*/
|
||||
public static Predicate isEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.isempty.toString(), boolean.class,
|
||||
geometry
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a predicate for testing the arguments for "is not empty" constraint.
|
||||
*
|
||||
* @param criteriaBuilder CriteriaBuilder
|
||||
* @param geometry geometry expression
|
||||
*
|
||||
* @return "is not empty" predicate
|
||||
*
|
||||
* @see SpatialRestrictions#isNotEmpty(String)
|
||||
*/
|
||||
public static Predicate isNotEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
|
||||
return isEmpty( criteriaBuilder, geometry )
|
||||
.not();
|
||||
}
|
||||
|
||||
private static Predicate booleanExpressionToPredicate(
|
||||
CriteriaBuilder criteriaBuilder,
|
||||
Expression<Boolean> expression) {
|
||||
return criteriaBuilder.equal( expression, true );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* 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.integration;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.spatial.HSMessageLogger;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.hana.HANASpatialDialect;
|
||||
import org.hibernate.spatial.integration.jts.JtsGeomEntity;
|
||||
import org.hibernate.spatial.predicate.SpatialPredicates;
|
||||
import org.hibernate.spatial.testing.SpatialDialectMatcher;
|
||||
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.Skip;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @see TestSpatialRestrictions
|
||||
*/
|
||||
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect")
|
||||
@SkipForDialect(value = HANASpatialDialect.class, comment = "The HANA dialect is tested via org.hibernate.spatial.dialect.hana.TestHANASpatialFunctions", jiraKey = "HHH-12426")
|
||||
public class TestSpatialPredicates extends SpatialFunctionalTestCase {
|
||||
|
||||
private static HSMessageLogger LOG = Logger.getMessageLogger(
|
||||
HSMessageLogger.class,
|
||||
TestSpatialPredicates.class.getName()
|
||||
);
|
||||
|
||||
protected HSMessageLogger getLogger() {
|
||||
return LOG;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void within() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.within ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getWithin( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.within( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filter() throws SQLException {
|
||||
if ( !dialectSupportsFiltering() ) {
|
||||
LOG.info( "Filtering is not supported by Dialect" );
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getFilter( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.filter( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contains() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.contains ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getContains( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.contains(
|
||||
criteriaBuilder,
|
||||
root.get( "geom" ),
|
||||
expectationsFactory.getTestPolygon()
|
||||
);
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crosses() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.crosses ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getCrosses( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.crosses( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void touches() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.touches ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getTouches( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.touches( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disjoint() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.disjoint ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getDisjoint( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.disjoint(
|
||||
criteriaBuilder,
|
||||
root.get( "geom" ),
|
||||
expectationsFactory.getTestPolygon()
|
||||
);
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eq() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.equals ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getEquals( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.eq( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intersects() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.intersects ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIntersects( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.intersects(
|
||||
criteriaBuilder,
|
||||
root.get( "geom" ),
|
||||
expectationsFactory.getTestPolygon()
|
||||
);
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overlaps() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.overlaps ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getOverlaps( expectationsFactory.getTestPolygon() );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.overlaps(
|
||||
criteriaBuilder,
|
||||
root.get( "geom" ),
|
||||
expectationsFactory.getTestPolygon()
|
||||
);
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dwithin() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.dwithin ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getDwithin( expectationsFactory.getTestPoint(), 30.0 );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.distanceWithin(
|
||||
criteriaBuilder,
|
||||
root.get( "geom" ),
|
||||
expectationsFactory.getTestPoint(),
|
||||
30.0
|
||||
);
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEmpty() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.isempty ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsEmpty();
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.isEmpty( criteriaBuilder, root.get( "geom" ) );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEmpty() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.isempty ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsNotEmpty();
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.isNotEmpty( criteriaBuilder, root.get( "geom" ) );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void havingSRID() throws SQLException {
|
||||
if ( !isSupportedByDialect( SpatialFunction.srid ) ) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.havingSRID( 4326 );
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 4326 );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
dbexpected = expectationsFactory.havingSRID( 31370 );
|
||||
predicateFactory = (criteriaBuilder, root) ->
|
||||
SpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 31370 );
|
||||
retrieveAndCompare( dbexpected, predicateFactory );
|
||||
}
|
||||
|
||||
private void retrieveAndCompare(
|
||||
Map<Integer, Boolean> dbexpected,
|
||||
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory) {
|
||||
try (Session session = openSession()) {
|
||||
Transaction tx = null;
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<JtsGeomEntity> criteriaQuery = criteriaBuilder.createQuery( JtsGeomEntity.class );
|
||||
Root<JtsGeomEntity> root = criteriaQuery.from( JtsGeomEntity.class );
|
||||
criteriaQuery.select( root )
|
||||
.where( predicateFactory.apply( criteriaBuilder, root ) );
|
||||
List<JtsGeomEntity> list = session.createQuery( criteriaQuery )
|
||||
.getResultList();
|
||||
compare( dbexpected, list );
|
||||
}
|
||||
finally {
|
||||
if ( tx != null ) {
|
||||
tx.rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void compare(Map<Integer, Boolean> dbexpected, List<JtsGeomEntity> list) {
|
||||
int cnt = dbexpected.entrySet()
|
||||
.stream()
|
||||
.filter( Map.Entry::getValue )
|
||||
.reduce( 0, (accumulator, entry) -> {
|
||||
if ( !findInList( entry.getKey(), list ) ) {
|
||||
fail( String.format( "Expected object with id= %d, but not found in result", entry.getKey() ) );
|
||||
}
|
||||
return accumulator + 1;
|
||||
}, Integer::sum );
|
||||
assertEquals( cnt, list.size() );
|
||||
LOG.infof( "Found %d objects within testsuite-suite polygon.", cnt );
|
||||
}
|
||||
|
||||
private boolean findInList(Integer id, List<JtsGeomEntity> list) {
|
||||
return list.stream()
|
||||
.anyMatch( entity -> entity.getId().equals( id ) );
|
||||
}
|
||||
}
|
|
@ -38,7 +38,6 @@ public class TestSupportFactories {
|
|||
|
||||
private static Class<? extends TestSupport> getSupportFactoryClass(Dialect dialect) {
|
||||
String canonicalName = dialect.getClass().getCanonicalName();
|
||||
|
||||
if ( ( dialect instanceof SpatialDialect ) && PostgreSQL82Dialect.class.isAssignableFrom( dialect.getClass() ) ) {
|
||||
//this test works because all postgis dialects ultimately derive of the Postgresql82Dialect
|
||||
return PostgisTestSupport.class;
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
package org.hibernate.spatial.testing.dialects.postgis;
|
||||
|
||||
|
||||
import org.hibernate.spatial.integration.TestSpatialFunctions;
|
||||
import org.hibernate.spatial.integration.TestSpatialPredicates;
|
||||
import org.hibernate.spatial.integration.TestSpatialRestrictions;
|
||||
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
|
||||
import org.hibernate.spatial.testing.DataSourceUtils;
|
||||
import org.hibernate.spatial.testing.SQLExpressionTemplate;
|
||||
|
@ -24,8 +27,10 @@ public class PostgisTestSupport extends TestSupport {
|
|||
|
||||
|
||||
public TestData createTestData(BaseCoreFunctionalTestCase testcase) {
|
||||
if ( testcase.getClass().getCanonicalName().contains( "TestSpatialFunctions" ) ||
|
||||
testcase.getClass().getCanonicalName().contains( "TestSpatialRestrictions" ) ) {
|
||||
Class<? extends BaseCoreFunctionalTestCase> testcaseClass = testcase.getClass();
|
||||
if ( testcaseClass == TestSpatialFunctions.class ||
|
||||
testcaseClass == TestSpatialRestrictions.class ||
|
||||
testcaseClass == TestSpatialPredicates.class ) {
|
||||
return TestData.fromFile( "postgis-functions-test.xml" );
|
||||
}
|
||||
return TestData.fromFile( "test-data-set.xml" );
|
||||
|
|
Loading…
Reference in New Issue