//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/io/datastore/sql/generic/GenericSQLWhereBuilder.java,v 1.21 2006/11/27 09:07:52 poth Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, 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
Aennchenstraße 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.io.datastore.sql.generic;
import java.sql.Types;
import java.util.List;
import org.deegree.i18n.Messages;
import org.deegree.io.JDBCConnection;
import org.deegree.io.datastore.DatastoreException;
import org.deegree.io.datastore.schema.MappedFeatureType;
import org.deegree.io.datastore.schema.content.MappingField;
import org.deegree.io.datastore.sql.StatementBuffer;
import org.deegree.io.datastore.sql.TableAliasGenerator;
import org.deegree.io.datastore.sql.VirtualContentProvider;
import org.deegree.io.datastore.sql.wherebuilder.WhereBuilder;
import org.deegree.io.quadtree.DBQuadtree;
import org.deegree.io.quadtree.DBQuadtreeManager;
import org.deegree.io.quadtree.IndexException;
import org.deegree.model.filterencoding.Filter;
import org.deegree.model.filterencoding.OperationDefines;
import org.deegree.model.filterencoding.SpatialOperation;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.ogcbase.SortProperty;
/**
* {@link WhereBuilder} implementation for the {@link GenericSQLDatastore}.
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author: poth $
*
* @version $Revision: 1.21 $, $Date: 2006/11/27 09:07:52 $
*/
class GenericSQLWhereBuilder extends WhereBuilder {
private final static String SQL_TRUE = "1=1";
private final static String SQL_FALSE = "1!=1";
private JDBCConnection jdbc;
/**
* Creates a new instance of <code>GenericSQLWhereBuilder</code> from the given parameters.
*
* @param ft
* requested feature type
* @param filter
* filter that restricts the matched features
* @param sortProperties
* sort criteria for the result, may be null or empty
* @param aliasGenerator
* used to generate unique table aliases
* @param vcProvider
* @param jdbc
* @throws DatastoreException
*/
public GenericSQLWhereBuilder( MappedFeatureType ft, Filter filter,
SortProperty[] sortProperties,
TableAliasGenerator aliasGenerator,
VirtualContentProvider vcProvider, JDBCConnection jdbc )
throws DatastoreException {
super( ft, filter, sortProperties, aliasGenerator, vcProvider );
this.jdbc = jdbc;
}
/**
* Generates an SQL-fragment for the given object.
*
* TODO: Implement BBOX faster using explicit B0X-constructor
*
* @throws DatastoreException
*/
@Override
protected void appendSpatialOperationAsSQL( StatementBuffer query, SpatialOperation operation )
throws DatastoreException {
switch ( operation.getOperatorId() ) {
case OperationDefines.BBOX: {
appendBBOXOperationAsSQL( query, operation );
break;
}
case OperationDefines.DISJOINT:
case OperationDefines.CROSSES:
case OperationDefines.EQUALS:
case OperationDefines.WITHIN:
case OperationDefines.OVERLAPS:
case OperationDefines.TOUCHES:
case OperationDefines.CONTAINS:
case OperationDefines.INTERSECTS:
case OperationDefines.DWITHIN:
case OperationDefines.BEYOND: {
query.append( SQL_TRUE );
break;
}
default: {
String msg = Messages.getMessage(
"DATASTORE_UNKNOWN_SPATIAL_OPERATOR",
OperationDefines.getNameById( operation.getOperatorId() ) );
throw new DatastoreException( msg );
}
}
}
/**
* Appends a constraint (FEATURE_ID IN (...)) to the given {@link StatementBuffer} which
* is generated by using the associated {@link DBQuadtree} index.
*
* @param query
* @param operation
* @throws DatastoreException
*/
private void appendBBOXOperationAsSQL( StatementBuffer query, SpatialOperation operation )
throws DatastoreException {
Envelope env = operation.getGeometry().getEnvelope();
try {
DBQuadtreeManager qtm = new DBQuadtreeManager( jdbc, this.rootFeatureType.getTable(),
"geometry", null );
Envelope qtEnv = qtm.getQuadtree().getRootBoundingBox();
if ( qtEnv.intersects( env ) ) {
// check if features within this bbox are available
// if not -> return an empty list
List ids = qtm.getQuadtree().query( env );
if ( ids.size() > 0 ) {
int dataType = Types.VARCHAR;
if ( ids.get( 0 ) instanceof Integer ) {
dataType = Types.INTEGER;
}
MappingField[] idFields = this.rootFeatureType.getGMLId().getIdFields();
if ( idFields.length > 1 ) {
String msg = "GenericSQLDatastore cannot handle composite feature ids.";
throw new DatastoreException( msg );
}
query.append( getRootTableAlias() + '.' + idFields[0].getField() + " IN (" );
for ( int i = 0; i < ids.size() - 1; i++ ) {
query.append( "?," );
if ( dataType == Types.VARCHAR ) {
query.addArgument( ( (String) ids.get( i ) ).trim(), Types.VARCHAR );
} else {
query.addArgument( ids.get( i ), Types.INTEGER );
}
}
if ( dataType == Types.VARCHAR ) {
query.addArgument( ( (String) ids.get( ids.size() - 1 ) ).trim(), Types.VARCHAR );
} else {
query.addArgument( ids.get( ids.size() - 1 ), Types.INTEGER );
}
query.append( "?)" );
} else {
query.append( SQL_FALSE );
}
} else {
query.append( SQL_FALSE );
}
} catch ( IndexException e ) {
LOG.logError( e.getMessage(), e );
throw new DatastoreException( "Could not initialize Quadtree: " + e.getMessage(), e );
}
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: GenericSQLWhereBuilder.java,v $
Revision 1.21 2006/11/27 09:07:52 poth
JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
Revision 1.20 2006/10/20 08:02:11 poth
required changes resulting from generalizing qudtree implementation
Revision 1.19 2006/10/11 15:52:00 mschneider
Add dummy condition if no feature ids match.
Revision 1.18 2006/10/11 15:31:16 poth
bug fix - ensure that at least one feature_ID has been retrieved from the quadtree before construction SQL where clause from it
Revision 1.17 2006/09/27 17:35:54 mschneider
Outfactored string constants.
Revision 1.16 2006/09/27 16:09:11 mschneider
Moved BBOX evaluation to GenericSQLWhereBuilder.
Revision 1.15 2006/09/19 14:54:12 mschneider
Cleaned up handling of VirtualContent, i.e. properties that are mapped to SQLFunctionCalls.
Revision 1.14 2006/08/15 17:40:45 mschneider
Javadoc fixes.
Revision 1.13 2006/08/14 16:50:55 mschneider
Changed to respect (optional) SortProperties.
Revision 1.12 2006/07/22 15:15:53 poth
performance enhancement
Revision 1.11 2006/06/01 12:40:56 mschneider
Added footer. Eliminated warnings.
********************************************************************** */