HHH-14800 Use FunctionContributor interface to register spatial functions

This commit is contained in:
Karel Maesen 2021-07-24 17:48:20 +02:00
parent 0b9de79a7d
commit f5f0ccfdd3
18 changed files with 153 additions and 56 deletions

View File

@ -41,7 +41,10 @@ public interface HSMessageLogger extends BasicLogger {
void connectionFinder(String className); void connectionFinder(String className);
@LogMessage(level = INFO) //maybe should be DEBUG? @LogMessage(level = INFO) //maybe should be DEBUG?
@Message(value = "hibernate-spatial using type contributions from : %s", id = 80000003) @Message(value = "hibernate-spatial adding type contributions from : %s", id = 80000003)
void typeContributions(String source); void typeContributions(String source);
@LogMessage(level = INFO) //maybe should be DEBUG?
@Message(value = "hibernate-spatial adding function contributions from : %s", id = 80000004)
void functionContributions(String source);
} }

View File

@ -5,23 +5,26 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.spatial.type; package org.hibernate.spatial.contributor;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
/** /**
* Internal contract for TypeContributor * Internal contract for TypeContributor
*/ */
abstract class SpatialTypeContributorImplementor { abstract class ContributorImplementor {
private final ServiceRegistry serviceRegistryegistry; private final ServiceRegistry serviceRegistryegistry;
SpatialTypeContributorImplementor(ServiceRegistry serviceRegistry) { ContributorImplementor(ServiceRegistry serviceRegistry) {
this.serviceRegistryegistry = serviceRegistry; this.serviceRegistryegistry = serviceRegistry;
} }
abstract void contribute(TypeContributions typeContributions); abstract void contributeTypes(TypeContributions typeContributions);
abstract void contributeFunctions(FunctionContributions functionContributions);
ServiceRegistry getServiceRegistryegistry() { ServiceRegistry getServiceRegistryegistry() {
return serviceRegistryegistry; return serviceRegistryegistry;

View File

@ -0,0 +1,44 @@
/*
* 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.contributor;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.ServiceRegistry;
class ContributorResolver {
private final static Map<Class<? extends Dialect>,
Function<ServiceRegistry, ContributorImplementor>> ContributorMap = new HashMap<>();
static {
//TypeContributorImplementor
ContributorMap.put( PostgreSQLDialect.class, PostgreSQLDialectContributor::new );
}
private ContributorResolver() {
}
static ContributorImplementor resolveSpatialtypeContributorImplementor(ServiceRegistry serviceRegistry) {
JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
Dialect dialect = jdbcServices.getDialect();
for ( Class<?> dialectClass : ContributorMap.keySet() ) {
if ( dialectClass.isAssignableFrom( dialect.getClass() ) ) {
return ContributorMap.get( dialectClass ).apply( serviceRegistry );
}
}
return null;
}
}

View File

@ -12,9 +12,13 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.spatial.type; package org.hibernate.spatial.contributor;
import java.util.Map;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor; import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType; import org.hibernate.spatial.GeolatteGeometryType;
@ -22,14 +26,15 @@ import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor; import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor;
import org.hibernate.spatial.JTSGeometryType; import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor; import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
import org.hibernate.spatial.dialect.postgis.PostgisFunctions;
public class PostgreSQLDialectTypeContributor extends SpatialTypeContributorImplementor{ public class PostgreSQLDialectContributor extends ContributorImplementor {
PostgreSQLDialectTypeContributor(ServiceRegistry serviceRegistry) { PostgreSQLDialectContributor(ServiceRegistry serviceRegistry) {
super( serviceRegistry ); super( serviceRegistry );
} }
public void contribute(TypeContributions typeContributions) { public void contributeTypes(TypeContributions typeContributions) {
HSMessageLogger.LOGGER.typeContributions( this.getClass().getCanonicalName() ); HSMessageLogger.LOGGER.typeContributions( this.getClass().getCanonicalName() );
typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) ); typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) );
typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) ); typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) );
@ -38,4 +43,13 @@ public class PostgreSQLDialectTypeContributor extends SpatialTypeContributorImpl
typeContributions.contributeJavaTypeDescriptor( GeolatteGeometryJavaTypeDescriptor.INSTANCE ); typeContributions.contributeJavaTypeDescriptor( GeolatteGeometryJavaTypeDescriptor.INSTANCE );
typeContributions.contributeJavaTypeDescriptor( JTSGeometryJavaTypeDescriptor.INSTANCE ); typeContributions.contributeJavaTypeDescriptor( JTSGeometryJavaTypeDescriptor.INSTANCE );
} }
@Override
void contributeFunctions(FunctionContributions functionContributions) {
HSMessageLogger.LOGGER.functionContributions( this.getClass().getCanonicalName() );
PostgisFunctions functions = new PostgisFunctions();
for( Map.Entry<String, SqmFunctionDescriptor> kv: functions) {
functionContributions.contributeFunction( kv.getKey(), kv.getValue() );
}
}
} }

View File

@ -0,0 +1,26 @@
/*
* 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.contributor;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.service.ServiceRegistry;
public class SpatialFunctionContributor implements FunctionContributor {
@Override
public void contributeTypes(
FunctionContributions functionContributions, ServiceRegistry serviceRegistry) {
ContributorImplementor contributorImplementor = ContributorResolver.resolveSpatialtypeContributorImplementor(
serviceRegistry );
if ( contributorImplementor != null ) {
contributorImplementor.contributeFunctions( functionContributions );
}
}
}

View File

@ -5,7 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.spatial.type; package org.hibernate.spatial.contributor;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor; import org.hibernate.boot.model.TypeContributor;
@ -15,10 +15,10 @@ public class SpatialTypeContributor implements TypeContributor {
@Override @Override
public void contribute( public void contribute(
TypeContributions typeContributions, ServiceRegistry serviceRegistry) { TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
SpatialTypeContributorImplementor contributorImplementor = TypeContributorResolver.resolve( serviceRegistry ); ContributorImplementor contributorImplementor = ContributorResolver.resolveSpatialtypeContributorImplementor( serviceRegistry );
if (contributorImplementor != null) { if (contributorImplementor != null) {
contributorImplementor.contribute( typeContributions ); contributorImplementor.contributeTypes( typeContributions );
} }
} }

View File

@ -11,6 +11,7 @@ import java.sql.CallableStatement;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
@ -76,6 +77,8 @@ public class PGGeometryTypeDescriptor implements JdbcTypeDescriptor {
return decoder.decode( pgValue ); return decoder.decode( pgValue );
} }
@Override @Override
public int getJdbcType() { public int getJdbcType() {
return 5432; return 5432;
@ -103,9 +106,20 @@ public class PGGeometryTypeDescriptor implements JdbcTypeDescriptor {
st.setObject( name, obj ); st.setObject( name, obj );
} }
//this and the next override is ONLY necessary as long as the distinction between SQLType and JDBC Type is not resolved
@Override
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
st.setNull( index, Types.OTHER );
}
@Override
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
st.setNull( name, Types.OTHER );
}
private PGobject toPGobject(X value, WrapperOptions options) throws SQLException { private PGobject toPGobject(X value, WrapperOptions options) throws SQLException {
final WkbEncoder encoder = Wkb.newEncoder( Wkb.Dialect.POSTGIS_EWKB_1 ); final WkbEncoder encoder = Wkb.newEncoder( Wkb.Dialect.POSTGIS_EWKB_1 );
final Geometry geometry = getJavaTypeDescriptor().unwrap( value, Geometry.class, options ); final Geometry<?> geometry = getJavaTypeDescriptor().unwrap( value, Geometry.class, options );
final String hexString = encoder.encode( geometry, ByteOrder.NDR ).toString(); final String hexString = encoder.encode( geometry, ByteOrder.NDR ).toString();
final PGobject obj = new PGobject(); final PGobject obj = new PGobject();
obj.setType( "geometry" ); obj.setType( "geometry" );

View File

@ -1,29 +0,0 @@
/*
* 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.type;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.ServiceRegistry;
class TypeContributorResolver {
private TypeContributorResolver() {
}
static SpatialTypeContributorImplementor resolve(ServiceRegistry serviceRegistry) {
JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
Dialect dialect = jdbcServices.getDialect();
if ( dialect.getClass().isAssignableFrom( PostgreSQLDialect.class ) ) {
return new PostgreSQLDialectTypeContributor( serviceRegistry );
}
return null;
}
}

View File

@ -0,0 +1,8 @@
#
# 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>.
#
org.hibernate.spatial.contributor.SpatialFunctionContributor

View File

@ -5,4 +5,4 @@
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. # See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
# #
org.hibernate.spatial.type.SpatialTypeContributor org.hibernate.spatial.contributor.SpatialTypeContributor

View File

@ -12,5 +12,9 @@
<bean id="serviceContributor" class="org.hibernate.spatial.integration.SpatialInitializer"/> <bean id="serviceContributor" class="org.hibernate.spatial.integration.SpatialInitializer"/>
<service ref="serviceContributor" interface="org.hibernate.service.spi.ServiceContributor"/> <service ref="serviceContributor" interface="org.hibernate.service.spi.ServiceContributor"/>
<bean id="spatialTypeContributor" class="org.hibernate.spatial.contributor.SpatialTypeContributor"/>
<service ref="spatialTypeContributor" interface="org.hibernate.boot.model.TypeContributor"/>
<bean id="spatialFunctionContributor" class="org.hibernate.spatial.contributor.SpatialFunctionContributor"/>
<service ref="spatialFunctionContributor" interface="org.hibernate.boot.model.FunctionContributor"/>
</blueprint> </blueprint>

View File

@ -40,6 +40,7 @@ import static org.junit.Assert.fail;
*/ */
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect") @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") @SkipForDialect(value = HANASpatialDialect.class, comment = "The HANA dialect is tested via org.hibernate.spatial.dialect.hana.TestHANASpatialFunctions", jiraKey = "HHH-12426")
@Deprecated
public class TestGeolatteSpatialPredicates extends SpatialFunctionalTestCase { public class TestGeolatteSpatialPredicates extends SpatialFunctionalTestCase {
private static final HSMessageLogger LOG = Logger.getMessageLogger( private static final HSMessageLogger LOG = Logger.getMessageLogger(

View File

@ -36,6 +36,7 @@ import static org.junit.Assert.fail;
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect") @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") @SkipForDialect(value = HANASpatialDialect.class, comment = "The HANA dialect is tested via org.hibernate.spatial.dialect.hana.TestHANASpatialFunctions", jiraKey = "HHH-12426")
@Deprecated
public class TestJTSSpatialPredicates extends SpatialFunctionalTestCase { public class TestJTSSpatialPredicates extends SpatialFunctionalTestCase {
private static final HSMessageLogger LOG = Logger.getMessageLogger( private static final HSMessageLogger LOG = Logger.getMessageLogger(

View File

@ -36,7 +36,7 @@ import static java.lang.String.format;
/** /**
* @author Karel Maesen, Geovise BVBA * @author Karel Maesen, Geovise BVBA
*/ */
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect") @Deprecated
public class TestSpatialFunctions extends SpatialFunctionalTestCase { public class TestSpatialFunctions extends SpatialFunctionalTestCase {
private static final HSMessageLogger LOG = Logger.getMessageLogger( private static final HSMessageLogger LOG = Logger.getMessageLogger(

View File

@ -19,6 +19,7 @@ import javax.persistence.Query;
import javax.persistence.SequenceGenerator; import javax.persistence.SequenceGenerator;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect; import org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect;
@ -34,7 +35,7 @@ import org.locationtech.jts.geom.Point;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@TestForIssue(jiraKey = "HHH-14523") @TestForIssue(jiraKey = "HHH-14523")
@RequiresDialect(PostgisPG95Dialect.class) @RequiresDialect(PostgreSQLDialect.class)
public class DirtyCheckingTest extends BaseEntityManagerFunctionalTestCase { public class DirtyCheckingTest extends BaseEntityManagerFunctionalTestCase {
private GeometryFactory gfact = new GeometryFactory(); private GeometryFactory gfact = new GeometryFactory();

View File

@ -15,7 +15,10 @@ import org.hibernate.testing.Skip;
/** /**
* @author Karel Maesen, Geovise BVBA * @author Karel Maesen, Geovise BVBA
* creation-date: 1/13/12 * creation-date: 1/13/12
*
* @deprecated Since we no longer require SpatialDialects
*/ */
@Deprecated
public class SpatialDialectMatcher implements Skip.Matcher { public class SpatialDialectMatcher implements Skip.Matcher {
@Override @Override
public boolean isMatch() { public boolean isMatch() {

View File

@ -165,7 +165,7 @@ public abstract class SpatialFunctionalTestCase extends BaseCoreFunctionalTestCa
*/ */
public boolean isSupportedByDialect(SpatialFunction spatialFunction) { public boolean isSupportedByDialect(SpatialFunction spatialFunction) {
Dialect dialect = getDialect(); Dialect dialect = getDialect();
throw new NotYetImplementedException(); return true;
} }

View File

@ -6,17 +6,21 @@
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. # See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
# #
# Default unit/integration test config. # Default unit/integration test config.
hibernate.dialect @db.dialect@
hibernate.connection.driver_class @jdbc.driver@
hibernate.connection.url @jdbc.url@
hibernate.connection.username @jdbc.user@
hibernate.connection.password @jdbc.pass@
hibernate.show_sql=true hibernate.connection.pool_size 5
hibernate.max_fetch_depth=5
hibernate.dialect=@db.dialect@ hibernate.show_sql false
hibernate.connection.driver_class=@jdbc.driver@ hibernate.format_sql true
hibernate.connection.url=@jdbc.url@
hibernate.connection.username=@jdbc.user@ hibernate.max_fetch_depth 5
hibernate.connection.password=@jdbc.pass@
hibernate.connection.init_sql @connection.init_sql@ hibernate.cache.region_prefix hibernate.test
#hibernate.cache.region_prefix hibernate.test hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
#hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
# #
## NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle ## NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle
#hibernate.jdbc.batch_versioned_data true #hibernate.jdbc.batch_versioned_data true