001: package org.geotools.data.ogr;
002:
003: import java.io.IOException;
004:
005: import org.gdal.gdal.gdal;
006: import org.gdal.ogr.Layer;
007: import org.geotools.data.DataSourceException;
008: import org.geotools.data.DataUtilities;
009: import org.geotools.data.FeatureWriter;
010: import org.geotools.data.jdbc.MutableFIDFeature;
011: import org.geotools.feature.DefaultFeatureType;
012: import org.geotools.feature.Feature;
013: import org.geotools.feature.FeatureType;
014: import org.geotools.feature.IllegalAttributeException;
015:
016: import com.vividsolutions.jts.geom.GeometryFactory;
017:
018: /**
019: * OGR feature writer leveraging OGR capabilities to rewrite a file using random
020: * access and in place deletes
021: *
022: * @author aaime
023: */
024: public class OGRDirectFeatureWriter implements FeatureWriter {
025:
026: private OGRFeatureReader reader;
027:
028: private FeatureType featureType;
029:
030: private Feature original;
031:
032: private MutableFIDFeature live;
033:
034: private Layer layer;
035:
036: private FeatureMapper mapper;
037:
038: private boolean deletedFeatures;
039:
040: /**
041: * Creates a new direct OGR feature writer, with the specified
042: * OGRFeatureReader and destination layer (it may be a different layer from
043: * the one the reader is working against)
044: *
045: * @param reader
046: * @param featureType
047: * @param layer
048: */
049: public OGRDirectFeatureWriter(OGRFeatureReader reader) {
050: this .reader = reader;
051: this .featureType = reader.getFeatureType();
052: this .layer = reader.layer;
053: this .mapper = new FeatureMapper(new GeometryFactory());
054: this .deletedFeatures = false;
055: }
056:
057: public void close() throws IOException {
058: if (reader != null) {
059: original = null;
060: live = null;
061: if ("ESRI Shapefile"
062: .equals(reader.ds.GetDriver().getName())
063: && deletedFeatures)
064: reader.ds.ExecuteSQL(
065: "REPACK " + reader.layer.GetName(), null, null);
066: reader.layer.SyncToDisk();
067: reader.close();
068: }
069: }
070:
071: public FeatureType getFeatureType() {
072: return featureType;
073: }
074:
075: public boolean hasNext() throws IOException {
076: return reader.hasNext();
077: }
078:
079: public Feature next() throws IOException {
080: if (live != null) {
081: write();
082: }
083:
084: try {
085: if (reader.hasNext()) {
086: original = reader.next();
087: live = new MutableFIDFeature(
088: (DefaultFeatureType) original.getFeatureType(),
089: original.getAttributes(new Object[original
090: .getFeatureType().getAttributeCount()]),
091: original.getID());
092: } else {
093: original = null;
094: live = new MutableFIDFeature(
095: (DefaultFeatureType) featureType, DataUtilities
096: .defaultValues(featureType), null);
097: }
098:
099: return live;
100: } catch (IllegalAttributeException e) {
101: throw new DataSourceException(
102: "Could not build next feature", e);
103: }
104: }
105:
106: public void remove() throws IOException {
107: int ogrId = mapper.convertGTFID(original);
108: if (layer.DeleteFeature(ogrId) != 0) {
109: throw new IOException(gdal.GetLastErrorMsg());
110: }
111: deletedFeatures = true;
112: }
113:
114: public void write() throws IOException {
115: if (live == null)
116: throw new IOException("No current feature to write");
117:
118: // this will return true only in update mode, otherwise original is null
119: boolean changed = live.equals(original);
120: if (!changed && original != null && layer == reader.layer) {
121: // nothing to do, just skip
122: } else if (changed && original != null && layer == reader.layer) {
123: // not equals, we're updating an existing one
124: layer.SetFeature(mapper.convertGTFeature(layer
125: .GetLayerDefn(), live));
126: } else {
127: org.gdal.ogr.Feature ogrFeature = mapper.convertGTFeature(
128: layer.GetLayerDefn(), original != null ? original
129: : live);
130: layer.CreateFeature(ogrFeature);
131: live.setID(mapper.convertOGRFID(featureType, ogrFeature));
132: ogrFeature.delete();
133: }
134:
135: // reset state
136: live = null;
137: original = null;
138: }
139:
140: }
|