Details
Assignee
UnassignedUnassignedReporter
Yoann RodièreYoann RodièrePriority
Major
Details
Details
Assignee
Unassigned
UnassignedReporter
Yoann Rodière
Yoann RodièrePriority
Created July 16, 2019 at 7:44 AM
Updated August 9, 2024 at 9:13 AM
Real-world applications are likely to rely on dedicated libraries to model their spatial types (points, polygons, ...).
Hibernate ORM already provides integration to JTS and geolatte-geom: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#spatial-overview
We should probably start with that.
Engine and backend
Keep the `GeoPoint` and related spatial types, but move them to the utils-common module, in a `spatial` package.
In that same package, add an interface that defines conversion logic:
public interface GeoPointModel<T> { double getGeoPointLatitude(T point); double getGeoPointLongitude(T point); T createGeoPoint(double latitude, double longitude); Class<T> getGeoPointType(); }
Implement this for our own
GeoPoint
type, with a staticGeoPointModel<GeoPoint> get()
method.In `IndexFieldTypeFactory`, add a method
<T> StandardIndexFieldTypeOptionsStep<?, T> asGeoPoint(GeoPointModel<T> model);
Add a default implementation for
asGeoPoint
which just uses theGeoPointModel
for our ownGeoPoint
type.Do the same for
GeoPolygon
andGeoBoundingBox
if relevant, with separateGeoPolygonModel
andGeoBoundingBoxModel
interfaces.Implement `asGeoPoint(GeoPointModel<T> model)` by changing all backend code: do not work with
GeoPoint
directly anymore, but work with a generic T and aGeoPointModel
In the DSLs, add variants of spatial-related methods taking a
GeoPointModel
in parameter. For example we'll addorg.hibernate.search.engine.search.dsl.predicate.SpatialPredicateInitialStep#within(GeoPointModel<T>)
and make sure the following steps are generic, we'll addorg.hibernate.search.engine.search.dsl.projection.SearchProjectionFactory#distance(String, GeoPointModel<T>, T>
, we'll addorg.hibernate.search.engine.search.dsl.sort.SearchSortFactory#byDistance(String, GeoPointModel<T>, T)
. Make sure to always keep the old method, but implement it as a default method which just uses our ownGeoPointModel
.Run tests, check everything still works
Add optional dependencies to JTS
Implement a JTSGeoPointModel
Adapt existing tests so that they can also be run with JTS
Add tests to check that mixing spatial models triggers clear exceptions.
Do the same with geolatte-geom?
POJO mapper: value bridges
Add a way to auto-detect available
GeoPointModel
et al. implementations on the classpath. Maybe use aGeoPointModelProvider
Java service? If so, useorg.hibernate.search.engine.environment.classpath.spi.ClassResolver#loadJavaServices
.Use this auto-detection to automatically add value bridges in
org.hibernate.search.mapper.pojo.bridge.mapping.impl.BridgeResolver
.Add appropriate tests
Make sure everything will work fine even when JTS is not on the classpath (the model should just be ignored)! We may want a dedicated test for that, perhaps in a separate module that explicitly excludes the dependency.
Convert
org.hibernate.search.integrationtest.showcase.library.model.Library
to use JTS or geolatte-geom, and to use a@GenericField
on alocation
property instead of a@GeoPointBinding
on twolatitude
/longitude
properties.Alternatives
Alternatively, we could make the spatial models a global setting, and change the signatures of our APIs to accept Object instead of GeoPoint et al.
Not sure this would be much better, though...
We could also avoid changing the backends too much by using the spatial models to convert from user APIs to our own representation (our own
GeoPoint
type), and only ever work with aGeoPoint
in the backends.Document
We will need to document clearly this feature, including in particular the versions of JTS and geolatte-geom we support.