/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * * 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.shapefile.indexed; import java.io.IOException; import java.util.List; import org.geotools.data.shapefile.ShapefileAttributeReader; import org.geotools.data.shapefile.dbf.IndexedDbaseFileReader; import org.geotools.data.shapefile.shp.ShapefileReader; import org.geotools.index.CloseableIterator; import org.geotools.index.Data; import org.opengis.feature.type.AttributeDescriptor; import com.vividsolutions.jts.geom.Envelope; /** * An AttributeReader implementation for shape. Pretty straightforward. <BR/>The * default geometry is at position 0, and all dbf columns follow. <BR/>The dbf * file may not be necessary, if not, just pass null as the DbaseFileReader * * * @source $URL$ */ public class IndexedShapefileAttributeReader extends ShapefileAttributeReader { protected CloseableIterator<Data> goodRecs; private Data next; public IndexedShapefileAttributeReader( List<AttributeDescriptor> attributes, ShapefileReader shp, IndexedDbaseFileReader dbf, CloseableIterator<Data> goodRecs) { this(attributes.toArray(new AttributeDescriptor[0]), shp, dbf, goodRecs); } /** * Create the shape reader * * @param atts - * the attributes that we are going to read. * @param shp - * the shape reader, required * @param dbf - * the dbf file reader. May be null, in this case no * attributes will be read from the dbf file * @param goodRecs * Collection of good indexes that match the query. */ public IndexedShapefileAttributeReader(AttributeDescriptor[] atts, ShapefileReader shp, IndexedDbaseFileReader dbf, CloseableIterator<Data> goodRecs) { super(atts, shp, dbf); this.goodRecs = goodRecs; } public void close() throws IOException { try { super.close(); } finally { if( goodRecs != null ){ goodRecs.close(); } goodRecs = null; } } public boolean hasNext() throws IOException { if (this.goodRecs != null) { while (!featureAvailable && this.goodRecs.hasNext()) { next = (Data) goodRecs.next(); Long l = (Long) next.getValue(1); shp.goTo((int) l.longValue()); record = shp.nextRecord(); // read the geometry, so that we can decide if this row is to be skipped or not Envelope envelope = record.envelope(); // ... if geometry is out of the target bbox, skip both geom and row if (targetBBox != null && !targetBBox.isNull() && !targetBBox.intersects(envelope)) { geometry = null; continue; // ... if the geometry is awfully small avoid reading it (unless it's a point) } else if (simplificationDistance > 0 && envelope.getWidth() < simplificationDistance && envelope.getHeight() < simplificationDistance) { try { if(screenMap != null && screenMap.checkAndSet(envelope)) { geometry = null; continue; } else { // if we are using the screenmap better provide a slightly modified // version of the geometry bounds or we'll end up with many holes // in the rendering geometry = record.getSimplifiedShape(screenMap); } } catch(Exception e) { geometry = record.getSimplifiedShape(); } // ... otherwise business as usual } else { geometry = record.shape(); } // read the dbf only if the geometry was not skipped if (dbf != null) { ((IndexedDbaseFileReader) dbf).goTo(record.number); row = dbf.readRow(); } else { row = null; } featureAvailable = true; } return featureAvailable; } else { return super.hasNext(); } } public void next() throws IOException { if (!hasNext()) throw new IndexOutOfBoundsException("No more features in reader"); featureAvailable = false; } }