/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * (C) Copyright IBM Corporation, 2005-2007. All rights reserved. * * 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; * version 2.1 of the License. * * 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. * */ package org.geotools.data.db2; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Logger; import org.geotools.data.DataSourceException; import org.geotools.data.Query; import org.geotools.data.Transaction; import org.geotools.data.jdbc.JDBCFeatureSource; import org.geotools.factory.CommonFactoryFinder; import org.geotools.filter.SQLEncoderException; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Literal; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.spatial.BBOX; import org.opengis.filter.spatial.BinarySpatialOperator; import org.opengis.filter.spatial.Intersects; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; /** * DB2 Feature Source implementation. Overrides functionality in * JDBCFeatureSource to provide more efficient or more appropriate DB2-specific * implementation. * * @author David Adler - IBM Corporation * * @source $URL$ * @source $URL: * http://svn.geotools.org/geotools/trunk/gt/modules/unsupported/db2/src/main/java/org/geotools/data/db2/DB2FeatureSource.java $ */ public class DB2FeatureSource extends JDBCFeatureSource { private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geotools.data.db2"); /** * Constructs a feature source based on a DB2 data store for a specified * feature type. * * @param dataStore * @param featureType */ public DB2FeatureSource(DB2DataStore dataStore, SimpleFeatureType featureType) { super(dataStore, featureType); } /** * Closes everything associated with a query, the ResultSet, Statement and * Connection. * * @param rs * the ResultSet * @param stmt * the Statement * @param conn * the Connection * @param transaction * the Transaction * @param e * the SQLException, if any, or null */ protected void closeAll(ResultSet rs, Statement stmt, Connection conn, Transaction transaction, SQLException e) { close(rs); close(stmt); close(conn, transaction, e); } /** * Gets the bounds of the feature using the specified query. * * @param query * a query object. * * @return the envelope representing the bounds of the features. * * @throws IOException * if there was an encoder problem. * @throws DataSourceException * if there was an error executing the query to get the bounds. */ public ReferencedEnvelope getBounds(Query query) throws IOException { ReferencedEnvelope env = new ReferencedEnvelope(); CoordinateReferenceSystem crs = null; LOGGER.fine("Query: " + query.toString()); if (getSchema() != null) { String typeName = getSchema().getTypeName(); GeometryDescriptor geomType = getSchema().getGeometryDescriptor(); if (geomType != null) { Filter filter = query.getFilter(); Class filterClass = filter.getClass(); if (filterClass == Intersects.class || filterClass == BBOX.class) { filter = fixNullGeomFilter(filter); } if (filter != Filter.EXCLUDE) { String sqlStmt = null; try { DB2SQLBuilder builder = (DB2SQLBuilder) ((DB2DataStore) this .getDataStore()).getSqlBuilder(typeName); LOGGER.fine("Filter: " + filter.toString()); sqlStmt = builder.buildSQLBoundsQuery(typeName, geomType, filter); } catch (SQLEncoderException e) { throw new IOException("SQLEncoderException: " + e); } Connection conn = null; Transaction transaction = null; Statement statement = null; ResultSet results = null; try { conn = getConnection(); transaction = getTransaction(); statement = conn.createStatement(); results = statement.executeQuery(sqlStmt); if (results.next()) { double minx = results.getDouble(1); double miny = results.getDouble(2); double maxx = results.getDouble(3); double maxy = results.getDouble(4); env = new ReferencedEnvelope(minx, maxx, miny, maxy, null); } else { env = new ReferencedEnvelope(); } } catch (SQLException e) { closeAll(results, statement, conn, transaction, e); System.out.println(e); throw new DataSourceException("Could not get bounds " + query.getHandle(), e); } closeAll(results, statement, conn, transaction, null); } crs = geomType.getCoordinateReferenceSystem(); env = new ReferencedEnvelope(env, crs); } } LOGGER.fine("Bounds: " + env.toString()); return env; } /* * Sometimes getBounds gets a filter with no geometry column - we substitute * the default geometry column, if one can be found. */ private Filter fixNullGeomFilter(Filter inFilter) { BinarySpatialOperator operator = (BinarySpatialOperator) inFilter; Filter filter = (Filter) inFilter; Class filterClass = inFilter.getClass(); double xmin = 0, ymin = 0, xmax = 0, ymax = 0; if (operator.getExpression1() == null) { String attName = null; GeometryDescriptor dg = getSchema().getGeometryDescriptor(); if (dg != null) attName = dg.getLocalName(); if (attName != null) { FilterFactory2 ff = (FilterFactory2) CommonFactoryFinder .getFilterFactory(null); if (filterClass == Intersects.class) { Intersects intersects = (Intersects) inFilter; Literal geomLiteral = (Literal) intersects.getExpression2(); Geometry geom = (Geometry) geomLiteral.getValue(); Envelope envelope = geom.getEnvelopeInternal(); xmin = envelope.getMinX(); ymin = envelope.getMinY(); xmax = envelope.getMaxX(); ymax = envelope.getMaxY(); PropertyName name = ff.property(attName); filter = ff.intersects(name,geomLiteral); } else if (filterClass == BBOX.class) { BBOX bbox = (BBOX) inFilter; xmin = bbox.getMinX(); ymin = bbox.getMinY(); xmax = bbox.getMaxX(); ymax = bbox.getMaxY(); } filter = ff.bbox(attName, xmin, ymin, xmax, ymax, ""); } } return filter; } }