HHH-14808 Basic SpatialPredicates
This commit is contained in:
parent
2bdd10389b
commit
5bae2d8196
|
@ -13,7 +13,6 @@ package org.hibernate.spatial;
|
|||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 4/18/13
|
||||
*/
|
||||
@Deprecated
|
||||
public interface Spatial {
|
||||
|
||||
}
|
||||
|
|
|
@ -13,12 +13,14 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
|
||||
import org.geolatte.geom.ByteBuffer;
|
||||
|
@ -29,6 +31,7 @@ import org.geolatte.geom.codec.WkbDecoder;
|
|||
import org.geolatte.geom.codec.WkbEncoder;
|
||||
import org.geolatte.geom.codec.Wkt;
|
||||
import org.geolatte.geom.codec.WktDecoder;
|
||||
import org.geolatte.geom.jts.JTS;
|
||||
import org.postgresql.util.PGobject;
|
||||
|
||||
/**
|
||||
|
@ -46,6 +49,18 @@ public class PGGeometryTypeDescriptor implements JdbcTypeDescriptor {
|
|||
// Type descriptor instance using EWKB v2 (postgis versions >= 2.2.2, see: https://trac.osgeo.org/postgis/ticket/3181)
|
||||
public static final PGGeometryTypeDescriptor INSTANCE_WKB_2 = new PGGeometryTypeDescriptor( Wkb.Dialect.POSTGIS_EWKB_2 );
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
if ( javaTypeDescriptor instanceof GeolatteGeometryJavaTypeDescriptor ) {
|
||||
return (value, dialect, wrapperOptions) -> "ST_GeomFromEWKT('" + value + "')";
|
||||
}
|
||||
return (value, dialect, wrapperOptions) -> "ST_GeomFromEWKT('" + jts2Gl( value ) + "')";
|
||||
}
|
||||
|
||||
private <T> Geometry<?> jts2Gl(T value) {
|
||||
return JTS.from( (org.locationtech.jts.geom.Geometry) value );
|
||||
}
|
||||
|
||||
private PGGeometryTypeDescriptor(Wkb.Dialect dialect) {
|
||||
wkbDialect = dialect;
|
||||
}
|
||||
|
@ -78,14 +93,13 @@ public class PGGeometryTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.OTHER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode(){
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return 5432;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,20 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
|
||||
import org.geolatte.geom.Envelope;
|
||||
import org.geolatte.geom.Geometry;
|
||||
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_CONTAINS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_CROSSES;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_DISJOINT;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_EQUALS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_INTERSECTS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_OVERLAPS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_TOUCHES;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_WITHIN;
|
||||
|
||||
/**
|
||||
* {@link JTSSpatialPredicates}, but for geolatte-geom.
|
||||
*
|
||||
|
@ -41,7 +50,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.equals.toString(), boolean.class,
|
||||
criteriaBuilder.function( ST_EQUALS.name(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
|
@ -82,9 +91,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.within.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_WITHIN.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -102,8 +109,7 @@ public class GeolatteSpatialPredicates {
|
|||
public static Predicate within(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return within( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
return within( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -123,7 +129,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.contains.toString(), boolean.class,
|
||||
criteriaBuilder.function( ST_CONTAINS.name(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
|
@ -164,7 +170,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.crosses.toString(), boolean.class,
|
||||
criteriaBuilder.function( ST_CROSSES.name(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
|
@ -205,9 +211,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.disjoint.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_DISJOINT.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -246,9 +250,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.intersects.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_INTERSECTS.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -266,8 +268,7 @@ public class GeolatteSpatialPredicates {
|
|||
public static Predicate intersects(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return intersects( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
return intersects( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -287,9 +288,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.overlaps.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_OVERLAPS.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -307,8 +306,7 @@ public class GeolatteSpatialPredicates {
|
|||
public static Predicate overlaps(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return overlaps( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
return overlaps( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -328,9 +326,7 @@ public class GeolatteSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.touches.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_TOUCHES.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -348,8 +344,7 @@ public class GeolatteSpatialPredicates {
|
|||
public static Predicate touches(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return touches( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
return touches( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,20 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
|
||||
import org.locationtech.jts.geom.Envelope;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_CONTAINS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_CROSSES;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_DISJOINT;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_EQUALS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_INTERSECTS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_OVERLAPS;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_TOUCHES;
|
||||
import static org.hibernate.spatial.CommonSpatialFunction.ST_WITHIN;
|
||||
|
||||
/**
|
||||
* A factory for spatial JPA Criteria API {@link Predicate}s.
|
||||
*
|
||||
|
@ -40,7 +48,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.equals.toString(), boolean.class, geometry1, geometry2 )
|
||||
criteriaBuilder.function( ST_EQUALS.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -75,7 +83,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.within.toString(), boolean.class, geometry1, geometry2 )
|
||||
criteriaBuilder.function( ST_WITHIN.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -110,9 +118,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.contains.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_CONTAINS.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -149,7 +155,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.crosses.toString(), boolean.class,
|
||||
criteriaBuilder.function( ST_CROSSES.name(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
);
|
||||
|
@ -188,9 +194,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.disjoint.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_DISJOINT.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -227,9 +231,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.intersects.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_INTERSECTS.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -247,8 +249,7 @@ public class JTSSpatialPredicates {
|
|||
public static Predicate intersects(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return intersects( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
return intersects( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -266,8 +267,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.overlaps.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
criteriaBuilder.function( ST_OVERLAPS.name(), boolean.class, geometry1, geometry2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -286,8 +286,7 @@ public class JTSSpatialPredicates {
|
|||
public static Predicate overlaps(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return overlaps( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
return overlaps( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -305,9 +304,7 @@ public class JTSSpatialPredicates {
|
|||
Expression<? extends Geometry> geometry2) {
|
||||
return booleanExpressionToPredicate(
|
||||
criteriaBuilder,
|
||||
criteriaBuilder.function( SpatialFunction.touches.toString(), boolean.class,
|
||||
geometry1, geometry2
|
||||
)
|
||||
criteriaBuilder.function( ST_TOUCHES.name(), boolean.class, geometry1, geometry2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -325,11 +322,11 @@ public class JTSSpatialPredicates {
|
|||
public static Predicate touches(
|
||||
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
|
||||
Geometry geometry2) {
|
||||
return touches( criteriaBuilder, geometry1,
|
||||
criteriaBuilder.literal( geometry2 )
|
||||
);
|
||||
return touches( criteriaBuilder, geometry1, criteriaBuilder.literal( geometry2 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * Create a predicate for testing the arguments for bounding box overlap constraint.
|
||||
// *
|
||||
|
|
|
@ -5,7 +5,14 @@
|
|||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.integration.functions;
|
||||
/*
|
||||
* 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.util.function.Function;
|
||||
|
||||
|
@ -21,36 +28,45 @@ import org.geolatte.geom.jts.JTS;
|
|||
* T
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
enum Model {
|
||||
public enum Model {
|
||||
|
||||
JTSMODEL(
|
||||
JtsGeomEntity.class,
|
||||
JTS::to
|
||||
JTS::to,
|
||||
org.locationtech.jts.geom.Geometry.class
|
||||
),
|
||||
GLMODEL(
|
||||
GeomEntity.class,
|
||||
geom -> geom
|
||||
geom -> geom,
|
||||
Geometry.class
|
||||
);
|
||||
|
||||
/**
|
||||
* Test Entity class
|
||||
*/
|
||||
final Class<?> entityClass;
|
||||
public final Class<?> entityClass;
|
||||
|
||||
|
||||
/**
|
||||
* How to translate from Geolatte Geometry class to the object class
|
||||
* expected by the entity geom property
|
||||
* How to translate from Geolatte Geometry to the geometry type
|
||||
* expected by the entity in this model
|
||||
*/
|
||||
final Function<Geometry, Object> from;
|
||||
public final Function<Geometry, Object> from;
|
||||
|
||||
/**
|
||||
* The geometry type in this model
|
||||
*/
|
||||
public final Class<?> geometryClass;
|
||||
|
||||
|
||||
Model(
|
||||
Class<?> entityClass,
|
||||
Function<Geometry, Object> from
|
||||
Function<Geometry, Object> from,
|
||||
Class<?> geometryClass
|
||||
) {
|
||||
this.entityClass = entityClass;
|
||||
this.from = from;
|
||||
this.geometryClass = geometryClass;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ import org.hibernate.spatial.testing.datareader.TestData;
|
|||
import org.hibernate.spatial.testing.datareader.TestDataElement;
|
||||
import org.hibernate.spatial.testing.datareader.TestSupport;
|
||||
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
|
||||
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
|
||||
import org.hibernate.spatial.testing.domain.GeomEntityLike;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DialectContext;
|
||||
|
@ -29,6 +30,7 @@ import static org.hibernate.spatial.testing.datareader.TestSupport.TestDataPurpo
|
|||
public class SpatialTestDataProvider {
|
||||
protected final static String JTS = "jts";
|
||||
protected final NativeSQLTemplates templates;
|
||||
protected final PredicateRegexes predicateRegexes;
|
||||
protected final Map<CommonSpatialFunction, String> hqlOverrides;
|
||||
private final TestData funcTestData;
|
||||
protected TestData testData;
|
||||
|
@ -38,6 +40,7 @@ public class SpatialTestDataProvider {
|
|||
try {
|
||||
TestSupport support = TestSupportFactories.instance().getTestSupportFactory( DialectContext.getDialect() );
|
||||
templates = support.templates();
|
||||
predicateRegexes = support.predicateRegexes();
|
||||
hqlOverrides = support.hqlOverrides();
|
||||
codec = support.codec();
|
||||
testData = support.createTestData( StoreRetrieveData );
|
||||
|
|
|
@ -16,8 +16,10 @@ package org.hibernate.spatial.integration.functions;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.hibernate.spatial.integration.Model;
|
||||
import org.hibernate.spatial.testing.IsSupportedBySpatial;
|
||||
import org.hibernate.spatial.testing.SpatialTestBase;
|
||||
import org.hibernate.spatial.testing.datareader.TestSupport;
|
||||
|
@ -42,14 +44,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("ALL")
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@RequiresDialectFeature(feature = IsSupportedBySpatial.class)
|
||||
@SessionFactory
|
||||
public class CommonFunctionTests extends SpatialTestBase {
|
||||
|
||||
public final static TestSupport.TestDataPurpose PURPOSE = TestSupport.TestDataPurpose.SpatialFunctionsData;
|
||||
|
||||
|
||||
List received;
|
||||
List expected;
|
||||
|
||||
|
@ -58,7 +60,6 @@ public class CommonFunctionTests extends SpatialTestBase {
|
|||
return PURPOSE;
|
||||
}
|
||||
|
||||
|
||||
@TestFactory
|
||||
public Stream<DynamicTest> testFunction() {
|
||||
|
||||
|
@ -73,13 +74,12 @@ public class CommonFunctionTests extends SpatialTestBase {
|
|||
|
||||
}
|
||||
|
||||
|
||||
protected Stream<DynamicTest> buildTests(FunctionTestTemplate template) {
|
||||
return Stream.of(
|
||||
template.getFunctionName(),
|
||||
template.getAltFunctionName()
|
||||
)
|
||||
.filter( s -> s != null )
|
||||
.filter( Objects::nonNull )
|
||||
.map( fn -> DynamicTest.dynamicTest(
|
||||
displayName( template, fn ), executableTest( template, fn )
|
||||
) );
|
||||
|
@ -94,12 +94,11 @@ public class CommonFunctionTests extends SpatialTestBase {
|
|||
);
|
||||
}
|
||||
|
||||
protected <T> Executable executableTest(FunctionTestTemplate template, String fnName) {
|
||||
Executable testF = () -> {
|
||||
protected Executable executableTest(FunctionTestTemplate template, String fnName) {
|
||||
return () -> {
|
||||
expected = template.executeNativeQuery( scope );
|
||||
received = template.executeHQL( scope, fnName );
|
||||
assertEquals( expected, received );
|
||||
};
|
||||
return testF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.query.NativeQuery;
|
|||
import org.hibernate.query.Query;
|
||||
import org.hibernate.spatial.CommonSpatialFunction;
|
||||
import org.hibernate.spatial.GeomCodec;
|
||||
import org.hibernate.spatial.integration.Model;
|
||||
import org.hibernate.spatial.testing.HQLTemplate;
|
||||
import org.hibernate.spatial.testing.NativeSQLTemplate;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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.predicates;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.spatial.integration.Model;
|
||||
import org.hibernate.spatial.predicate.GeolatteSpatialPredicates;
|
||||
import org.hibernate.spatial.predicate.JTSSpatialPredicates;
|
||||
import org.hibernate.spatial.testing.HSReflectionUtil;
|
||||
import org.hibernate.spatial.testing.IsSupportedBySpatial;
|
||||
import org.hibernate.spatial.testing.SpatialTestBase;
|
||||
import org.hibernate.spatial.testing.datareader.TestSupport;
|
||||
|
||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.junit.platform.commons.JUnitException;
|
||||
|
||||
import org.geolatte.geom.G2D;
|
||||
import org.geolatte.geom.Polygon;
|
||||
|
||||
import static org.geolatte.geom.builder.DSL.g;
|
||||
import static org.geolatte.geom.builder.DSL.polygon;
|
||||
import static org.geolatte.geom.builder.DSL.ring;
|
||||
import static org.geolatte.geom.crs.CoordinateReferenceSystems.WGS84;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@RequiresDialectFeature(feature = IsSupportedBySpatial.class)
|
||||
@SessionFactory
|
||||
public class GeolatteSpatialPredicatesTest extends SpatialTestBase {
|
||||
|
||||
public final static TestSupport.TestDataPurpose PURPOSE = TestSupport.TestDataPurpose.SpatialFunctionsData;
|
||||
|
||||
static final Polygon<G2D> filter = polygon(
|
||||
WGS84,
|
||||
ring( g( 0, 0 ), g( 0, 10 ), g( 10, 10 ), g( 10, 0 ), g( 0, 0 ) )
|
||||
);
|
||||
|
||||
@Override
|
||||
public TestSupport.TestDataPurpose purpose() {
|
||||
return PURPOSE;
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
public Stream<DynamicTest> testFactory() {
|
||||
return
|
||||
predicateRegexes.all()
|
||||
.flatMap( entry -> Stream.of(
|
||||
new Args( entry.getKey(), entry.getValue(), Model.GLMODEL ),
|
||||
new Args( entry.getKey(), entry.getValue(), Model.JTSMODEL )
|
||||
) )
|
||||
.map( args -> DynamicTest.dynamicTest(
|
||||
displayName( args ),
|
||||
testPredicate(
|
||||
args.method,
|
||||
args.regex,
|
||||
args.model
|
||||
)
|
||||
) );
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Executable testPredicate(final String key, final String regex, Model model) {
|
||||
return () -> scope.inSession( session -> {
|
||||
SQLStatementInspector inspector = SQLStatementInspector.extractFromSession( session );
|
||||
inspector.clear();
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery query = getCriteriaQuery(
|
||||
key,
|
||||
criteriaBuilder,
|
||||
model
|
||||
);
|
||||
List resultList = session.createQuery( query ).getResultList();
|
||||
String stmt = inspector.getSqlQueries()
|
||||
.get( 0 )
|
||||
.toLowerCase( Locale.ROOT );
|
||||
//TODO -- can't we use a (hamcrest) matcher here?
|
||||
assertTrue( stmt.matches( regex ) );
|
||||
} );
|
||||
}
|
||||
|
||||
private CriteriaQuery getCriteriaQuery(
|
||||
String key,
|
||||
CriteriaBuilder criteriaBuilder, Model model) {
|
||||
CriteriaQuery query = criteriaBuilder.createQuery( model.entityClass );
|
||||
Root root = query.from( model.entityClass );
|
||||
Method method = predicateMethod( key, model );
|
||||
finalizeQuery( criteriaBuilder, model, query, root, method );
|
||||
return query;
|
||||
}
|
||||
|
||||
private void finalizeQuery(
|
||||
CriteriaBuilder criteriaBuilder,
|
||||
Model model,
|
||||
CriteriaQuery query,
|
||||
Root root,
|
||||
Method method) {
|
||||
try {
|
||||
query.select( root )
|
||||
.where( (Expression<Boolean>) method.invoke(
|
||||
null, criteriaBuilder, root.get( "geom" ), model.from.apply( filter ) ) );
|
||||
}
|
||||
catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new JUnitException( "Failure to invoke Geometry Predicate", e );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Method predicateMethod(String key, Model model) {
|
||||
Class predicateFactoryClass = model == Model.JTSMODEL ?
|
||||
JTSSpatialPredicates.class :
|
||||
GeolatteSpatialPredicates.class;
|
||||
return HSReflectionUtil.getStaticMethod(
|
||||
predicateFactoryClass,
|
||||
key,
|
||||
CriteriaBuilder.class, Expression.class, model.geometryClass
|
||||
);
|
||||
}
|
||||
|
||||
private String displayName(Args args) {
|
||||
return String.format( "Predicate %s on %s", args.method, args.model.entityClass.getSimpleName() );
|
||||
}
|
||||
}
|
||||
|
||||
class Args {
|
||||
final String method;
|
||||
final String regex;
|
||||
final Model model;
|
||||
|
||||
public Args(String method, String regex, Model model) {
|
||||
this.method = method;
|
||||
this.regex = regex;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.testing;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
//TODO -- fold this into ReflectionUtil
|
||||
public class HSReflectionUtil {
|
||||
|
||||
/**
|
||||
* Get target method
|
||||
*
|
||||
* @param target target class
|
||||
* @param methodName method name
|
||||
* @param parameterTypes method parameter types
|
||||
*
|
||||
* @return return value
|
||||
*/
|
||||
public static Method getStaticMethod(Class target, String methodName, Class... parameterTypes) {
|
||||
try {
|
||||
return target.getMethod( methodName, parameterTypes );
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException( e );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,13 @@ import org.hibernate.dialect.PostgreSQLDialect;
|
|||
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureCheck;
|
||||
|
||||
/**
|
||||
* Checks if the Dialect is actually supported by Spatial
|
||||
*
|
||||
* Note: the tests in this module need to be explicitly enabled in the gradle build config. So this check is
|
||||
* maybe no longer needed.
|
||||
*
|
||||
*/
|
||||
public class IsSupportedBySpatial implements DialectFeatureCheck {
|
||||
@Override
|
||||
public boolean apply(Dialect dialect) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.spatial.CommonSpatialFunction;
|
|||
import org.hibernate.spatial.GeomCodec;
|
||||
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
|
||||
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
|
||||
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -36,6 +37,11 @@ public abstract class TestSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
//TODO -- make this abstract
|
||||
public PredicateRegexes predicateRegexes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<CommonSpatialFunction, String> hqlOverrides() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.testing.dialects;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public class PredicateRegexes {
|
||||
|
||||
protected final Map<String, String> regexes = new HashMap<>();
|
||||
|
||||
// Note that we alias the function invocation so that
|
||||
// we can map the return value to the required type
|
||||
public PredicateRegexes() {
|
||||
regexes.put(
|
||||
"overlaps",
|
||||
"select .* from .* where st_overlaps\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"intersects",
|
||||
"select .* from .* where st_intersects\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"crosses",
|
||||
"select .* from .* where st_crosses\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"contains",
|
||||
"select .* from .* where st_contains\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"disjoint",
|
||||
"select .* from .* where st_disjoint\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"touches",
|
||||
"select .* from .* where st_touches\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"within",
|
||||
"select .* from .* where st_within\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
regexes.put(
|
||||
"eq",
|
||||
"select .* from .* where st_equals\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=\\?.*"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public Stream<Map.Entry<String, String>> all() {
|
||||
return this.regexes.entrySet().stream();
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ import org.hibernate.spatial.testing.AbstractExpectationsFactory;
|
|||
import org.hibernate.spatial.testing.datareader.TestData;
|
||||
import org.hibernate.spatial.testing.datareader.TestSupport;
|
||||
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
|
||||
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
|
||||
import org.hibernate.spatial.testing.dialects.postgis.PostgisNativeSQLTemplates;
|
||||
|
||||
import org.geolatte.geom.Geometry;
|
||||
|
@ -25,6 +26,11 @@ public class CockroachDBTestSupport extends TestSupport {
|
|||
return new PostgisNativeSQLTemplates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PredicateRegexes predicateRegexes() {
|
||||
return new CrPredicateRegexes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestData createTestData(TestDataPurpose purpose) {
|
||||
switch ( purpose ) {
|
||||
|
@ -50,3 +56,5 @@ public class CockroachDBTestSupport extends TestSupport {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class CrPredicateRegexes extends PredicateRegexes{ }
|
|
@ -18,6 +18,7 @@ import org.hibernate.spatial.testing.AbstractExpectationsFactory;
|
|||
import org.hibernate.spatial.testing.datareader.TestData;
|
||||
import org.hibernate.spatial.testing.datareader.TestSupport;
|
||||
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
|
||||
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
|
||||
|
||||
import org.geolatte.geom.Geometry;
|
||||
import org.geolatte.geom.codec.Wkt;
|
||||
|
@ -35,6 +36,9 @@ public class PostgisTestSupport extends TestSupport {
|
|||
return new PostgisNativeSQLTemplates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PredicateRegexes predicateRegexes(){ return new PostgisPredicateRegexes();}
|
||||
|
||||
//TODO put this in its own class (analogous to NativeSQLTemplates)
|
||||
@Override
|
||||
public Map<CommonSpatialFunction, String> hqlOverrides() {
|
||||
|
@ -68,3 +72,5 @@ public class PostgisTestSupport extends TestSupport {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class PostgisPredicateRegexes extends PredicateRegexes { }
|
|
@ -34,7 +34,6 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa
|
|||
#hibernate.connection.username hibernate_orm_test
|
||||
#hibernate.connection.password hibernate_orm_test
|
||||
|
||||
>>>>>>> 5aae4945cb (Update CockroachDB support for 6)
|
||||
## GeoDb (H2 spatial extension)
|
||||
##
|
||||
#hibernate.dialect org.hibernate.spatial.dialect.h2geodb.GeoDBDialect
|
||||
|
|
Loading…
Reference in New Issue