//$HeadURL$
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2008 by:
Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.igeo.dataadapter.database.postgis;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.StringTools;
import org.deegree.igeo.config.JDBCConnection;
import org.deegree.igeo.dataadapter.database.AbstractDatabaseLoader;
import org.deegree.igeo.mapmodel.DatabaseDatasource;
import org.deegree.io.DBPoolException;
import org.deegree.io.datastore.sql.postgis.PGgeometryAdapter;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GeometryException;
import org.deegree.model.spatialschema.GeometryFactory;
import org.deegree.model.spatialschema.Surface;
import org.postgis.PGboxbase;
import org.postgis.PGgeometry;
import org.postgresql.PGConnection;
/**
* class for loading data as feature collection from a postgis database
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version. $Revision$, $Date$
*/
public class PostgisDataLoader extends AbstractDatabaseLoader {
private static final ILogger LOG = LoggerFactory.getLogger( PostgisDataLoader.class );
private static final String GEOMETRY_DATATYPE_NAME = "geometry";
private static final String BOX3D_DATATYPE_NAME = "box3d";
private static final String PG_GEOMETRY_CLASS_NAME = "org.postgis.PGgeometry";
private static final String PG_BOX3D_CLASS_NAME = "org.postgis.PGbox3d";
private static Class<?> pgGeometryClass;
private static Class<?> pgBox3dClass;
static {
try {
pgGeometryClass = Class.forName( PG_GEOMETRY_CLASS_NAME );
} catch ( ClassNotFoundException e ) {
LOG.logError( "Cannot find class '" + PG_GEOMETRY_CLASS_NAME + "'.", e );
}
try {
pgBox3dClass = Class.forName( PG_BOX3D_CLASS_NAME );
} catch ( ClassNotFoundException e ) {
LOG.logError( "Cannot find class '" + PG_BOX3D_CLASS_NAME + "'.", e );
}
}
/**
*
* @param datasource
*/
public PostgisDataLoader( DatabaseDatasource datasource ) {
super( datasource );
}
@Override
protected Object handleGeometryValue( Object value, CoordinateSystem crs )
throws GeometryException {
value = PGgeometryAdapter.wrap( (PGgeometry) value, crs );
return value;
}
@Override
protected PreparedStatement createPreparedStatement( DatabaseDatasource datasource, Envelope envelope,
Connection conn )
throws GeometryException, SQLException {
// special case if all features need to be requested, eg. for the classification
if ( envelope == null ) {
return conn.prepareStatement( datasource.getSqlTemplate() );
}
PreparedStatement stmt;
String envCRS = envelope.getCoordinateSystem().getLocalName();
String nativeCRS = getSRSCode( datasource.getSRID() );
PGboxbase box = PGgeometryAdapter.export( envelope );
Surface surface = GeometryFactory.createSurface( envelope, envelope.getCoordinateSystem() );
PGgeometry pggeom = PGgeometryAdapter.export( surface, Integer.parseInt( envCRS ) );
StringBuffer query = new StringBuffer( 1000 );
if ( nativeCRS.equals( "-1" ) ) {
query.append( " (" );
query.append( datasource.getGeometryFieldName() );
query.append( " && ST_SetSRID( ?, -1) " );
query.append( " AND ST_Intersects(" );
query.append( datasource.getGeometryFieldName() );
query.append( ",ST_SetSRID( ?,-1 ) ) ) " );
} else {
// use the bbox operator (&&) to filter using the spatial index
query.append( " (" );
query.append( datasource.getGeometryFieldName() );
query.append( " && ST_Transform(ST_SetSRID( ?, " );
query.append( envCRS );
query.append( "), " );
query.append( nativeCRS );
query.append( ")) AND ST_Intersects(" );
query.append( datasource.getGeometryFieldName() );
query.append( ",ST_Transform(?, " );
query.append( nativeCRS );
query.append( "))" );
}
String sql = datasource.getSqlTemplate();
if ( sql.trim().toUpperCase().endsWith( " WHERE" ) ) {
LOG.logDebug( "created SQL: ", sql + query );
stmt = conn.prepareStatement( sql + query );
} else if ( sql.trim().toUpperCase().indexOf( " WHERE " ) < 0 ) {
LOG.logDebug( "created SQL: ", sql + " WHERE " + query );
stmt = conn.prepareStatement( sql + " WHERE " + query );
} else {
LOG.logDebug( "created SQL: ", sql + " AND " + query );
stmt = conn.prepareStatement( sql + " AND " + query );
}
// TODO
// if connection is not available ask user updated connection parameters
stmt.setObject( 1, box, java.sql.Types.OTHER );
stmt.setObject( 2, pggeom, java.sql.Types.OTHER );
stmt.setMaxRows( maxFeatures );
// seems that not every postgres version supports this
// stmt.setQueryTimeout( timeout );
LOG.logDebug( "created statement" + stmt );
return stmt;
}
/**
* @param srid
* @return
*/
private static String getSRSCode( String srid ) {
if ( srid.indexOf( ":" ) > -1 ) {
String[] t = StringTools.toArray( srid, ":", false );
return t[t.length - 1];
}
return srid;
}
@Override
protected Connection acquireConnection( JDBCConnection jdbc )
throws DBPoolException, SQLException {
Connection conn = super.acquireConnection( jdbc );
PGConnection pgConn = (PGConnection) conn;
pgConn.addDataType( GEOMETRY_DATATYPE_NAME, pgGeometryClass );
pgConn.addDataType( BOX3D_DATATYPE_NAME, pgBox3dClass );
return conn;
}
}