/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2011-2016, Geomatys * * 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.geotoolkit.db; import com.vividsolutions.jts.geom.Geometry; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import org.apache.sis.feature.FeatureExt; import org.apache.sis.internal.feature.AttributeConvention; import org.apache.sis.util.ArgumentChecks; import org.geotoolkit.data.FeatureReader; import org.geotoolkit.data.FeatureStoreRuntimeException; import static org.geotoolkit.db.JDBCFeatureStoreUtilities.*; import org.geotoolkit.db.reverse.PrimaryKey; import org.geotoolkit.factory.Hints; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.db.dialect.SQLDialect; import org.geotoolkit.geometry.jts.JTS; import org.opengis.coverage.Coverage; import org.opengis.feature.AttributeType; import org.opengis.feature.Feature; import org.opengis.feature.FeatureType; import org.opengis.feature.Operation; import org.opengis.feature.PropertyType; import org.opengis.util.GenericName; /** * JDBC Feature reader, both simple and complexe features. * * @author Johann Sorel (Geomatys) * @module */ public class JDBCFeatureReader implements FeatureReader { protected final FeatureType type; protected final DefaultJDBCFeatureStore store; protected final PrimaryKey pkey; protected final String sql; protected final Hints hints; //array of properties for faster access when simple type protected final PropertyType[] properties; protected final Object[] values; /** * statement,result set that is being worked from. */ protected final Statement st; protected final ResultSet rs; protected final Connection cx; protected final boolean release ; /** the next feature */ private Feature feature = null; protected boolean closed = false; public JDBCFeatureReader(final DefaultJDBCFeatureStore store, final String sql, final FeatureType type, Connection cnx, boolean release, final Hints hints) throws SQLException,DataStoreException { ArgumentChecks.ensureNonNull("Connection", cnx); final GenericName typeName = type.getName(); final String name = typeName.tip().toString(); this.type = type; this.store = store; PrimaryKey pk = store.getDatabaseModel().getPrimaryKey(typeName.toString()); this.pkey = (pk==null)? new PrimaryKey("qom") : pk; this.properties = this.type.getProperties(true).toArray(new PropertyType[0]); this.values = new Object[this.properties.length]; this.sql = sql; this.cx = cnx; this.st = cx.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); this.st.setFetchSize(store.getFetchSize()); try { this.rs = this.st.executeQuery(sql); } catch (SQLException sqle){ throw new SQLException(sqle.getMessage()+" with query :"+ sql,sqle); } this.hints = hints; this.release = release; } public JDBCFeatureReader(final JDBCFeatureReader other) throws SQLException { this.type = other.type; this.store = other.store; this.pkey = other.pkey; this.sql = other.sql; this.hints = other.hints; this.st = other.st; this.rs = other.rs; this.cx = other.cx; this.release = other.release; this.properties = other.properties; this.values = new Object[this.properties.length]; } @Override public FeatureType getFeatureType() { return type; } @Override public Feature next() throws FeatureStoreRuntimeException { findNext(); final Feature f = feature; feature = null; return f; } @Override public boolean hasNext() throws FeatureStoreRuntimeException { findNext(); return feature != null; } private void findNext(){ if(feature!=null) return; try { if(rs.next()){ feature = toFeature(rs); } } catch (SQLException e) { throw new FeatureStoreRuntimeException(e); } catch (DataStoreException e) { throw new FeatureStoreRuntimeException(e); } } protected Feature toFeature(ResultSet rs) throws SQLException, DataStoreException{ final Feature feature = type.newInstance(); int k=0; for(final PropertyType ptype : type.getProperties(true)){ if(ptype instanceof Operation){ //do nothing }else if(ptype instanceof AttributeType){ //single value attribut final Object value = readSimpleValue(store.getDialect(), rs, k+1, ptype); feature.setPropertyValue(ptype.getName().toString(), value); k++; } } return feature; } @Override public void close() { closed = true; closeSafe(store.getLogger(),(release)?cx:null,st,rs); } @Override public void remove() { throw new UnsupportedOperationException("Not supported."); } @Override protected void finalize() throws Throwable { if(release && !closed){ store.getLogger().log(Level.WARNING, "A JDBC Reader has not been closed"); close(); } super.finalize(); } public static Object readSimpleValue(final SQLDialect dialect, final ResultSet rs, int index, PropertyType desc) throws SQLException{ if(AttributeConvention.isGeometryAttribute(desc)){ final AttributeType gatt = (AttributeType) desc; final Class valueClass = gatt.getValueClass(); if(Coverage.class.isAssignableFrom(valueClass)){ //raster type final Coverage coverage; try { coverage = dialect.decodeCoverageValue(gatt, rs, index); } catch (IOException e) { throw new SQLException(e); } return coverage; }else{ //vector type final Geometry geom; try { geom = dialect.decodeGeometryValue(gatt, rs, index); } catch (IOException e) { throw new SQLException(e); } if(geom != null && geom.getUserData() == null){ //set crs is not set JTS.setCRS(geom, FeatureExt.getCRS(gatt)); } return geom; } }else{ return dialect.decodeAttributeValue((AttributeType)desc, rs, index); } } }