/*
* 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;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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.Transaction;
import org.geotools.factory.Hints;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.IllegalAttributeException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
/**
* Uses PropertyAttributeWriter to generate a property file on disk.
*
* @source $URL$
*/
public class PropertyFeatureWriter implements
FeatureWriter<SimpleFeatureType, SimpleFeature> {
PropertyDataStore store;
File read;
PropertyAttributeReader reader;
File write;
PropertyAttributeWriter writer;
SimpleFeature origional = null;
SimpleFeature live = null;
public PropertyFeatureWriter(PropertyDataStore dataStore, String typeName)
throws IOException {
store = dataStore;
File dir = store.directory;
read = new File(dir, typeName + ".properties");
write = File.createTempFile(typeName + System.currentTimeMillis(),
null, dir);
reader = new PropertyAttributeReader(read);
writer = new PropertyAttributeWriter(write, reader.type);
}
// constructor end
// getFeatureType start
public SimpleFeatureType getFeatureType() {
return reader.type;
}
// 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 {
writer.next();
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);
}
}
writer.writeFeatureID(fid);
for (int i = 0; i < f.getAttributeCount(); i++) {
Object value = f.getAttribute(i);
writer.write(i, value );
}
}
// writeImplementation end
// next start
public SimpleFeature next() throws IOException {
if (writer == null) {
throw new IOException("Writer has been closed");
}
String fid = null;
SimpleFeatureType type = reader.type;
try {
if (hasNext()) {
reader.next(); // grab next line
fid = reader.getFeatureID();
Object values[] = new Object[reader.getAttributeCount()];
for (int i = 0; i < reader.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());
store.listenerManager.fireFeaturesChanged(typeName, autoCommit,
bounds, false);
} else {
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;
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.next();
writer.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;
}
// close end
}