/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.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.geotoolkit.data.shapefile.indexed; import static org.geotoolkit.data.shapefile.lock.ShpFileType.*; import java.io.IOException; import java.net.URI; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.logging.Level; import org.apache.sis.internal.feature.AttributeConvention; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.data.FeatureStoreRuntimeException; import org.geotoolkit.data.FeatureReader; import org.geotoolkit.data.shapefile.ShapefileFeatureStoreFactory; import org.geotoolkit.data.shapefile.ShapefileFeatureWriter; import org.geotoolkit.data.shapefile.lock.ShpFileType; import org.geotoolkit.data.shapefile.lock.ShpFiles; import org.geotoolkit.data.shapefile.lock.StorageFile; import org.geotoolkit.data.shapefile.fix.IndexedFidWriter; import org.geotoolkit.nio.IOUtilities; import org.opengis.feature.Feature; /** * A FeatureWriter for ShapefileDataStore. Uses a write and annotate technique * to avoid buffering attributes and geometries. Because the shape and dbf * require header information which can only be obtained by reading the entire * series of Features, the headers are updated after the initial write * completes. * @module */ class IndexedShapefileFeatureWriter extends ShapefileFeatureWriter{ private IndexedShapefileFeatureStore indexedShapefileFeatureStore; private IndexedFidWriter fidWriter; private String currentFid; public IndexedShapefileFeatureWriter(final String typeName, final ShpFiles shpFiles, final IndexedShapefileAttributeReader attsReader, final FeatureReader featureReader, final IndexedShapefileFeatureStore featurestore, final Charset charset) throws DataStoreException,IOException { super(featurestore, typeName, shpFiles, attsReader, featureReader, charset); this.indexedShapefileFeatureStore = featurestore; if (!featurestore.indexUseable(FIX)) { this.fidWriter = IndexedFidWriter.EMPTY_WRITER; } else { final StorageFile storageFile = getLocker().getStorageFile(FIX); storageFiles.put(FIX, storageFile); this.fidWriter = getLocker().getFIXWriter(storageFile); } //runnable called when closing writer, we use it to rebuild id index and quadtree postClose = new Runnable() { @Override public void run() { try { if (shpFiles.isWritable()) { if (indexedShapefileFeatureStore.needsGeneration(ShpFileType.FIX)) { IndexedFidWriter.generate(shpFiles); } deleteFile(ShpFileType.QIX); if (indexedShapefileFeatureStore.treeType == IndexType.QIX) { indexedShapefileFeatureStore .buildQuadTree(indexedShapefileFeatureStore.maxDepth); } } } catch (Throwable e) { indexedShapefileFeatureStore.treeType = IndexType.NONE; ShapefileFeatureStoreFactory.LOGGER.log(Level.WARNING, "Error creating Spatial index", e); } } }; } @Override public Feature next() throws FeatureStoreRuntimeException { // closed already, error! if (featureReader == null) { throw new FeatureStoreRuntimeException("Writer closed"); } // we have to write the current feature back into the stream if (currentFeature != null) { write(); } final long next; try { next = fidWriter.next(); } catch (IOException ex) { throw new FeatureStoreRuntimeException(ex); } currentFid = getFeatureType().getName().tip().toString()+ "." + next; Feature feature = super.next(); return feature; } @Override protected String nextFeatureId() { return currentFid; } @Override public void remove() throws FeatureStoreRuntimeException { try { fidWriter.remove(); } catch (IOException ex) { throw new FeatureStoreRuntimeException(ex); } super.remove(); } @Override public void write() throws FeatureStoreRuntimeException { try { fidWriter.write(); } catch (IOException ex) { throw new FeatureStoreRuntimeException(ex); } //ensure the user did not modify the id between next() and write() calls currentFeature.setPropertyValue(AttributeConvention.IDENTIFIER_PROPERTY.toString(), currentFid); super.write(); } @Override protected void doClose() throws FeatureStoreRuntimeException { super.doClose(); try{ fidWriter.close(); }catch(Throwable e){ indexedShapefileFeatureStore.treeType = IndexType.NONE; ShapefileFeatureStoreFactory.LOGGER.log(Level.WARNING, "Error creating Feature ID index", e); } } private void deleteFile(final ShpFileType shpFileType) { final URI uri = shpFiles.getURI(shpFileType); try { Path toDelete = IOUtilities.toPath(uri); Files.deleteIfExists(toDelete); } catch(IOException ex){ //should not happen throw new RuntimeException(ex); } } public String id() { return getClass().getName(); } }