/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2007-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.ogr; import java.io.IOException; import org.gdal.gdal.gdal; import org.gdal.ogr.Layer; import org.geotools.data.FeatureWriter; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.filter.identity.FeatureIdImpl; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.FeatureType; import com.vividsolutions.jts.geom.GeometryFactory; /** * OGR feature writer leveraging OGR capabilities to rewrite a file using random access and in place * deletes * * @author aaime * * * * @source $URL$ * http://svn.osgeo.org/geotools/trunk/modules/unsupported/ogr/src/main/java/org/geotools * /data/ogr/OGRDirectFeatureWriter.java $ */ public class OGRDirectFeatureWriter implements FeatureWriter { private OGRFeatureReader reader; private SimpleFeatureType featureType; private SimpleFeature original; private SimpleFeature live; private Layer layer; private FeatureMapper mapper; private boolean deletedFeatures; /** * Creates a new direct OGR feature writer, with the specified OGRFeatureReader and destination * layer (it may be a different layer from the one the reader is working against) * * @param reader * @param featureType * @param layer */ public OGRDirectFeatureWriter(OGRFeatureReader reader) { this.reader = reader; this.featureType = reader.getFeatureType(); this.layer = reader.layer; this.mapper = new FeatureMapper(featureType, new GeometryFactory()); this.deletedFeatures = false; } public void close() throws IOException { if (reader != null) { original = null; live = null; if ("ESRI Shapefile".equals(reader.ds.GetDriver().getName()) && deletedFeatures) reader.ds.ExecuteSQL("REPACK " + reader.layer.GetName(), null, null); reader.layer.SyncToDisk(); reader.close(); } } public FeatureType getFeatureType() { return featureType; } public boolean hasNext() throws IOException { return reader.hasNext(); } public SimpleFeature next() throws IOException { if (live != null) { write(); } if (reader.hasNext()) { original = reader.next(); live = SimpleFeatureBuilder.copy(original); } else { original = null; live = SimpleFeatureBuilder.template(featureType, null); } return live; } public void remove() throws IOException { int ogrId = mapper.convertGTFID(original); if (layer.DeleteFeature(ogrId) != 0) { throw new IOException(gdal.GetLastErrorMsg()); } deletedFeatures = true; } public void write() throws IOException { if (live == null) throw new IOException("No current feature to write"); // this will return true only in update mode, otherwise original is null boolean changed = live.equals(original); if (!changed && original != null && layer == reader.layer) { // nothing to do, just skip } else if (changed && original != null && layer == reader.layer) { // not equals, we're updating an existing one layer.SetFeature(mapper.convertGTFeature(layer.GetLayerDefn(), live)); } else { org.gdal.ogr.Feature ogrFeature = mapper.convertGTFeature(layer.GetLayerDefn(), original != null ? original : live); layer.CreateFeature(ogrFeature); ((FeatureIdImpl) live.getIdentifier()).setID(mapper.convertOGRFID(featureType, ogrFeature)); ogrFeature.delete(); } // reset state live = null; original = null; } }