/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-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.property.ng; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.nio.channels.FileChannel; import org.geotools.data.DataSourceException; import org.geotools.data.DataUtilities; import org.geotools.data.FeatureWriter; import org.geotools.data.Query; import org.geotools.data.Transaction; import org.geotools.data.store.ContentFeatureSource; import org.geotools.data.store.ContentState; import org.geotools.factory.Hints; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.util.Converters; import org.opengis.feature.IllegalAttributeException; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import com.vividsolutions.jts.geom.Geometry; /** * Uses PropertyAttributeWriter to generate a property file on disk. * * * @source $URL$ */ public class PropertyFeatureWriter implements FeatureWriter<SimpleFeatureType, SimpleFeature> { PropertyDataStore store; ContentFeatureSource featureSource; File read; PropertyFeatureReader reader; File write; BufferedWriter writer; SimpleFeatureType type; SimpleFeature origional = null; SimpleFeature live = null; private ContentState state; public PropertyFeatureWriter(ContentFeatureSource source, ContentState contentState, Query query, boolean append) throws IOException { this.state = contentState; this.featureSource = source; PropertyDataStore store = (PropertyDataStore) contentState.getEntry().getDataStore(); String namespaceURI = store.getNamespaceURI(); String typeName = query.getTypeName(); read = store.file; File dir = read.getParentFile(); write = File.createTempFile(typeName + System.currentTimeMillis(),null, dir); // start reading reader = new PropertyFeatureReader(namespaceURI, read ); type = reader.getFeatureType(); // open writer writer = new BufferedWriter(new FileWriter(write)); // write header writer.write("_="); writer.write(DataUtilities.spec(type)); } // constructor end // getFeatureType start public SimpleFeatureType getFeatureType() { return reader.getFeatureType(); } // getFeatureType end // hasNext start public boolean hasNext() throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); } if (live != null && origional != null) { // we have returned something to the user, // and it has not been writen out or removed // writeImplementation(origional); origional = null; live = null; } return reader.hasNext(); } // hasNext end // writeImplementation start private void writeImplementation(SimpleFeature f) throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); } writer.newLine(); writer.flush(); String fid = f.getID(); if( Boolean.TRUE.equals( f.getUserData().get(Hints.USE_PROVIDED_FID) ) ){ if( f.getUserData().containsKey(Hints.PROVIDED_FID)){ fid = (String) f.getUserData().get(Hints.PROVIDED_FID); } } writeFeatureID(fid); for (int i = 0; i < f.getAttributeCount(); i++) { Object value = f.getAttribute(i); write(i, value ); } } public void writeFeatureID(String fid) throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); } writer.write(fid); } public void write(int position, Object attribute) throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); } writer.write(position == 0 ? "=" : "|"); if (attribute == null) { writer.write("<null>"); // nothing! } else if( attribute instanceof String){ // encode newlines String txt = (String) attribute; txt = txt.replace("\n", "\\n"); txt = txt.replace("\r", "\\r"); writer.write( txt ); } else if (attribute instanceof Geometry) { Geometry geometry = (Geometry) attribute; writer.write( geometry.toText() ); } else { String txt = Converters.convert( attribute, String.class ); if( txt == null ){ // could not convert? txt = attribute.toString(); } writer.write( txt ); } } // writeImplementation end // next start public SimpleFeature next() throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); } String fid = null; try { if (hasNext()) { reader.next(); // grab next line fid = reader.fid; Object values[] = new Object[type.getAttributeCount()]; for (int i = 0; i < type.getAttributeCount(); i++) { values[i] = reader.read(i); } origional = SimpleFeatureBuilder.build(type, values, fid); live = SimpleFeatureBuilder.copy(origional); return live; } else { fid = type.getTypeName() + "." + System.currentTimeMillis(); Object values[] = DataUtilities.defaultValues(type); origional = null; live = SimpleFeatureBuilder.build(type, values, fid); return live; } } catch (IllegalAttributeException e) { String message = "Problem creating feature " + (fid != null ? fid : ""); throw new DataSourceException(message, e); } } // next end // write start public void write() throws IOException { if (live == null) { throw new IOException("No current feature to write"); } if (live.equals(origional)) { writeImplementation(origional); } else { writeImplementation(live); String typeName = live.getFeatureType().getTypeName(); Transaction autoCommit = Transaction.AUTO_COMMIT; if (origional != null) { ReferencedEnvelope bounds = new ReferencedEnvelope(); bounds.include(live.getBounds()); bounds.include(origional.getBounds()); state.fireFeatureUpdated(featureSource, live, bounds); //store.listenerManager.fireFeaturesChanged(typeName, autoCommit, bounds, false); } else { state.fireFeatureAdded(featureSource, live); // store.listenerManager.fireFeaturesAdded(typeName, autoCommit, ReferencedEnvelope.reference(live.getBounds()), false); } } origional = null; live = null; } // write end // remove start public void remove() throws IOException { if (live == null) { throw new IOException("No current feature to remove"); } if (origional != null) { String typeName = live.getFeatureType().getTypeName(); Transaction autoCommit = Transaction.AUTO_COMMIT; state.fireFeatureRemoved(featureSource,origional); //store.listenerManager.fireFeaturesRemoved(typeName, autoCommit,ReferencedEnvelope.reference(origional.getBounds()), false); } origional = null; live = null; // prevent live and remove from being written out } // remove end // close start public void close() throws IOException { if (writer == null) { throw new IOException("writer already closed"); } // write out remaining contents from reader // if applicable while (reader.hasNext()) { reader.next(); // advance writer.newLine(); writer.flush(); echoLine(reader.line); // echo unchanged } writer.close(); reader.close(); writer = null; reader = null; read.delete(); if (write.exists() && !write.renameTo(read)) { FileChannel out = new FileOutputStream(read).getChannel(); FileChannel in = new FileInputStream(write).getChannel(); try { long len = in.size(); long copied = out.transferFrom(in, 0, in.size()); if (len != copied) { throw new IOException("unable to complete write"); } } finally { in.close(); out.close(); } } read = null; write = null; store = null; } public void echoLine(String line) throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); } if (line == null) { return; } writer.write(line); } // close end }