/*
* 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.sql.BatchUpdateException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import com.vividsolutions.jts.geom.Geometry;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.testing.AfterClassOnce;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Karel Maesen, Geovise BVBA
* creation-date: Sep 30, 2010
*/
public abstract class SpatialFunctionalTestCase extends BaseCoreFunctionalTestCase {
protected final static String JTS = "jts";
protected final static String GEOLATTE = "geolatte";
protected TestData testData;
protected DataSourceUtils dataSourceUtils;
protected GeometryEquality geometryEquality;
protected AbstractExpectationsFactory expectationsFactory;
/**
* Inserts the test data via a direct route (JDBC).
*/
public void prepareTest() {
try {
dataSourceUtils.insertTestData( testData );
}
catch (BatchUpdateException e) {
throw new RuntimeException( e.getNextException() );
}
catch (SQLException e) {
throw new RuntimeException( e );
}
}
/**
* Removes the test data.
*/
public void cleanupTest() {
cleanUpTest( "jts" );
cleanUpTest( "geolatte" );
}
private void cleanUpTest(String pckg) {
Session session = null;
Transaction tx = null;
try {
session = openSession();
tx = session.beginTransaction();
String hql = String.format( "delete from org.hibernate.spatial.integration.%s.GeomEntity", pckg );
Query q = session.createQuery( hql );
q.executeUpdate();
tx.commit();
}
catch (Exception e) {
if ( tx != null ) {
tx.rollback();
}
}
finally {
if ( session != null ) {
session.close();
}
}
}
/**
* Override to also ensure that the SpatialTestSupport utility is
* initialised together with the Hibernate <code>Configuration</code>.
*
* @return
*/
protected void afterConfigurationBuilt(Configuration cfg) {
super.afterConfigurationBuilt( cfg );
initializeSpatialTestSupport( serviceRegistry() );
}
private void initializeSpatialTestSupport(ServiceRegistry serviceRegistry) {
try {
TestSupport support = TestSupportFactories.instance().getTestSupportFactory( getDialect() );
dataSourceUtils = support.createDataSourceUtil( serviceRegistry );
expectationsFactory = support.createExpectationsFactory( dataSourceUtils );
testData = support.createTestData( this );
geometryEquality = support.createGeometryEquality();
}
catch (Exception e) {
throw new RuntimeException( e );
}
}
/**
* Overwrites the afterSessionFactoryBuilt() method in BaseCoreFunctionalTestCase.
* <p/>
* Mostly used to register spatial metadata in databases such as Oracle Spatial.
*/
public void afterSessionFactoryBuilt() {
dataSourceUtils.afterCreateSchema();
}
/**
* Cleans up the dataSourceUtils
*
* @throws SQLException
*/
@AfterClassOnce
public void closeDataSourceUtils() throws SQLException {
dataSourceUtils.close();
}
public String getBaseForMappings() {
return "";
}
public String[] getMappings() {
return new String[] {};
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
org.hibernate.spatial.integration.geolatte.GeomEntity.class,
org.hibernate.spatial.integration.jts.GeomEntity.class
};
}
/**
* Returns true if the spatial dialect supports the specified function
*
* @param spatialFunction
*
* @return
*/
public boolean isSupportedByDialect(SpatialFunction spatialFunction) {
SpatialDialect dialect = (SpatialDialect) getDialect();
return dialect.supports( spatialFunction );
}
/**
* Supports true if the spatial dialect supports filtering (e.g. ST_overlap, MBROverlap, SDO_FILTER)
*
* @return
*/
public boolean dialectSupportsFiltering() {
SpatialDialect dialect = (SpatialDialect) getDialect();
return dialect.supportsFiltering();
}
abstract protected HSMessageLogger getLogger();
/**
* Adds the query results to a Map.
* <p/>
* Each row is added as a Map entry with the first column the key,
* and the second the value. It is assumed that the first column is an
* identifier of a type assignable to Integer.
*
* @param result map of
* @param query the source Query
* @param <T> type of the second column in the query results
*/
protected <T> void addQueryResults(Map<Integer, T> result, Query query) {
List<Object[]> rows = (List<Object[]>) query.list();
if ( rows.size() == 0 ) {
getLogger().warn( "No results returned for query!!" );
}
for ( Object[] row : rows ) {
Integer id = (Integer) row[0];
T val = (T) row[1];
result.put( id, val );
}
}
protected <T> void compare(Map<Integer, T> expected, Map<Integer, T> received, String geometryType) {
for ( Map.Entry<Integer, T> entry : expected.entrySet() ) {
Integer id = entry.getKey();
getLogger().debug( "Case :" + id );
getLogger().debug( "expected: " + expected.get( id ) );
getLogger().debug( "received: " + received.get( id ) );
compare( id, entry.getValue(), received.get( id ), geometryType );
}
}
protected void compare(Integer id, Object expected, Object received, String geometryType) {
assertTrue( expected != null || received == null );
if ( expected instanceof byte[] ) {
assertArrayEquals( "Failure on testsuite-suite for case " + id, (byte[]) expected, (byte[]) received );
}
else if ( expected instanceof Geometry ) {
if ( JTS.equals( geometryType ) ) {
if ( !(received instanceof Geometry) ) {
fail(
"Expected a JTS Geometry, but received an object of type " + received.getClass()
.getCanonicalName()
);
}
assertTrue(
"Failure on testsuite-suite for case " + id,
geometryEquality.test( (Geometry) expected, (Geometry) received )
);
}
else {
if ( !(received instanceof org.geolatte.geom.Geometry) ) {
fail(
"Expected a Geolatte Geometry, but received an object of type " + received.getClass()
.getCanonicalName()
);
}
assertTrue(
"Failure on testsuite-suite for case " + id,
geometryEquality.test(
(Geometry) expected,
(Geometry) org.geolatte.geom.jts.JTS.to( (org.geolatte.geom.Geometry) received )
)
);
}
}
else {
if ( expected instanceof Long ) {
assertEquals( "Failure on testsuite-suite for case " + id, ((Long) expected).intValue(), received );
}
else {
assertEquals( "Failure on testsuite-suite for case " + id, expected, received );
}
}
}
}