|
From: <svn...@os...> - 2011-12-18 11:54:40
|
Author: jive
Date: 2011-12-18 03:54:33 -0800 (Sun, 18 Dec 2011)
New Revision: 38423
Added:
trunk/modules/library/data/src/main/java/org/geotools/data/store/EventContentFeatureWriter.java
Removed:
trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyAttributeWriter.java
Modified:
trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java
trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureStore.java
trunk/modules/library/data/src/main/java/org/geotools/data/store/DiffTransactionState.java
trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCFeatureStore.java
trunk/modules/unsupported/csv/src/main/java/org/geotools/data/csv/CSVFeatureStore.java
trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyFeatureStore.java
Log:
Initial cut of EventContentFeatureWriter for GEOT-3956
Modified: trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java
===================================================================
--- trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -860,13 +860,26 @@
* If a subclass can handle transactions natively it should override this
* method to return <code>true</code> and deal with transactions on its own,
* including firing feature modifications events.
- * @return
+ * @return true if transaction independence has custom implementation
*/
protected boolean canTransact() {
return false;
}
/**
+ * Determines if the store takes responsibility for issuing events.
+ * <p>
+ * If a subclass issue events (as part of its low level writer implementation)
+ * then it should override this method to return true.
+ *
+ * @return true if event notification has custom implementation
+ */
+ protected boolean canEvent() {
+ return false;
+ }
+
+
+ /**
* Creates a new feature source for the specified query.
* <p>
* If the current feature source already has a defining query it is joined
Modified: trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureStore.java
===================================================================
--- trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureStore.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureStore.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -141,6 +141,7 @@
query = resolvePropertyNames(query);
FeatureWriter<SimpleFeatureType, SimpleFeature> writer;
+
if (!canTransact() && transaction != null && transaction != Transaction.AUTO_COMMIT) {
DiffTransactionState state = (DiffTransactionState) getTransaction().getState(getEntry());
FeatureReader<SimpleFeatureType, SimpleFeature> reader = getReader(query);
@@ -148,6 +149,10 @@
} else {
writer = getWriterInternal(query, flags);
+ // events
+ if (canTransact() && !canEvent()){
+ writer = new EventContentFeatureWriter(this, writer );
+ }
// filtering
if (!canFilter()) {
if (query.getFilter() != null && query.getFilter() != Filter.INCLUDE) {
Modified: trunk/modules/library/data/src/main/java/org/geotools/data/store/DiffTransactionState.java
===================================================================
--- trunk/modules/library/data/src/main/java/org/geotools/data/store/DiffTransactionState.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/library/data/src/main/java/org/geotools/data/store/DiffTransactionState.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -79,35 +79,8 @@
/**
* Will apply differences to store.
*
- * @see org.geotools.data.Transaction.State#commit()
- */
- public synchronized void commit() throws IOException {
- applyDiff();
- }
-
- @Override
- /**
- * @see org.geotools.data.Transaction.State#rollback()
- */
- public synchronized void rollback() throws IOException {
- diff.clear(); // rollback differences
- state.fireBatchFeatureEvent(false);
- }
-
- @Override
-
- /**
- * @see org.geotools.data.Transaction.State#addAuthorization(java.lang.String)
- */
- public synchronized void addAuthorization(String AuthID) throws IOException {
- // not required for TransactionStateDiff
- }
-
- /**
- * Called by commit() to apply one set of diff
- *
* <p>
- * The provided <code> will be modified as the differences are applied,
+ * The provided diff will be modified as the differences are applied,
* If the operations are all successful diff will be empty at
* the end of this process.
* </p>
@@ -131,9 +104,10 @@
* @param diff differences to apply to FeatureWriter
*
* @throws IOException If the entire diff cannot be writen out
- * @throws DataSourceException If the entire diff cannot be writen out
+ * @t
+ * @see org.geotools.data.Transaction.State#commit()
*/
- void applyDiff() throws IOException {
+ public synchronized void commit() throws IOException {
if (diff.isEmpty()) {
return; // nothing to do
}
@@ -242,4 +216,22 @@
}
}
}
+
+ @Override
+ /**
+ * @see org.geotools.data.Transaction.State#rollback()
+ */
+ public synchronized void rollback() throws IOException {
+ diff.clear(); // rollback differences
+ state.fireBatchFeatureEvent(false);
+ }
+
+ @Override
+
+ /**
+ * @see org.geotools.data.Transaction.State#addAuthorization(java.lang.String)
+ */
+ public synchronized void addAuthorization(String AuthID) throws IOException {
+ // not required for TransactionStateDiff
+ }
}
\ No newline at end of file
Added: trunk/modules/library/data/src/main/java/org/geotools/data/store/EventContentFeatureWriter.java
===================================================================
--- trunk/modules/library/data/src/main/java/org/geotools/data/store/EventContentFeatureWriter.java (rev 0)
+++ trunk/modules/library/data/src/main/java/org/geotools/data/store/EventContentFeatureWriter.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -0,0 +1,184 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2011, 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.store;
+
+import java.io.IOException;
+
+import org.geotools.data.BatchFeatureEvent;
+import org.geotools.data.Diff;
+import org.geotools.data.DiffFeatureWriter;
+import org.geotools.data.FeatureWriter;
+import org.geotools.data.Transaction;
+import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+
+/**
+ * FeatureWriter wrapper that issues events modifications as required.
+ * <p>
+ * It is the responsibility of a FeatureStore to issue events to interested parties as content is modified. The {@link ContentState} keeps track of
+ * the listeners, while {@link EventContentFeatureWriter} is willing to fire the events as needed.
+ * <p>
+ * Event generation happens in two passes:
+ * <ul>
+ * <li>As features are modified events are sent out one at a time</li>
+ * <li>When commit() or rollback() is called a "batch" event is sent out</li>
+ * </ul>
+ * The only trick is the comment() event contains our only indication of the final FeatureIDs generated for new features. The
+ * {@link BatchFeatureEvent} maintains a map of BEFORE/AFTER values allowing any interested party to update their seleciton.
+ * <p>
+ * Please note that if you are using {@link DiffFeatureWriter} it sends out events on its own.
+ *
+ * @author Jody Garnett (LISASoft)
+ *
+ * @source $URL$
+ */
+public class EventContentFeatureWriter implements FeatureWriter<SimpleFeatureType, SimpleFeature> {
+
+ ContentState state;
+
+ SimpleFeature feature; // live value supplied by writer
+
+ ContentFeatureStore store;
+
+ FeatureWriter<SimpleFeatureType, SimpleFeature> writer;
+
+
+ /**
+ * EventContentFeatureWriter construction.
+ *
+ * @param reader
+ * @param diff
+ * @param filter
+ */
+ public EventContentFeatureWriter(ContentFeatureStore store,
+ FeatureWriter<SimpleFeatureType, SimpleFeature> writer) {
+ this.store = store;
+ this.writer = writer;
+ this.state = store.getState();
+
+ Transaction t = state.getTransaction();
+ if( t != Transaction.AUTO_COMMIT ){
+ // auto commit does not issue batch events
+ t.putState(this,new EventContentTransactionState());
+ }
+ }
+
+ /**
+ * Supplys FeatureTypeFrom reader
+ *
+ * @see org.geotools.data.FeatureWriter#getFeatureType()
+ */
+ public SimpleFeatureType getFeatureType() {
+ return writer.getFeatureType();
+ }
+
+ /**
+ * Next Feature from reader or new content.
+ *
+ * @see org.geotools.data.FeatureWriter#next()
+ */
+ public SimpleFeature next() throws IOException {
+ feature = writer.next();
+ return feature;
+ }
+
+ /**
+ * @see org.geotools.data.FeatureWriter#remove()
+ */
+ public void remove() throws IOException {
+ state.fireFeatureRemoved(store, feature);
+ writer.remove();
+ }
+
+ /**
+ * Writes out the current feature.
+ *
+ * @throws IOException
+ *
+ * @see org.geotools.data.FeatureWriter#write()
+ */
+ public void write() throws IOException {
+ writer.write();
+ if (feature == null) {
+ throw new IOException("No feature available to write");
+ }
+ if (writer.hasNext()) {
+ // modify existing feature
+ ReferencedEnvelope bounds = ReferencedEnvelope.reference(feature.getBounds());
+ state.fireFeatureUpdated(store, feature, bounds);
+ feature = null;
+ } else {
+ // modify a new feature - ie we are adding something
+ state.fireFeatureAdded(store, feature);
+ }
+ }
+
+ /**
+ * Query for more content.
+ *
+ * @see org.geotools.data.FeatureWriter#hasNext()
+ */
+ public boolean hasNext() throws IOException {
+ return writer.hasNext();
+ }
+
+ /**
+ * Clean up resources associated with this writer.
+ *
+ * <p>
+ * Diff is not clear()ed as it is assumed that it belongs to a Transaction.State object and may yet be written out.
+ * </p>
+ *
+ * @see org.geotools.data.FeatureWriter#close()
+ */
+ public void close() throws IOException {
+ Transaction t = state.getTransaction();
+ if (t != Transaction.AUTO_COMMIT ){
+ t.removeState(this);
+ }
+ if( writer != null ){
+ writer.close();
+ writer = null;
+ }
+ feature = null;
+ }
+ /**
+ * Used to detect commit() and rollback() in order to fire batch feature events.
+ * @author jody
+ *
+ */
+ class EventContentTransactionState implements Transaction.State {
+ @Override
+ public void commit() throws IOException {
+ store.getState().fireBatchFeatureEvent(true);
+ }
+ @Override
+ public void rollback() throws IOException {
+ store.getState().fireBatchFeatureEvent(false);
+ }
+ @Override
+ public void setTransaction(Transaction transaction) {
+ // not needed to issue batch events (as they pretend to be from AUTO_COMMIT)
+ }
+ @Override
+ public void addAuthorization(String AuthID) throws IOException {
+ // functionality not restricted by lock authorisation
+ }
+ }
+
+}
\ No newline at end of file
Modified: trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCFeatureStore.java
===================================================================
--- trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCFeatureStore.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCFeatureStore.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -93,6 +93,11 @@
getDataStore().getSQLDialect().addSupportedHints(jdbcHints);
hints=Collections.unmodifiableSet(jdbcHints);
}
+
+ /** We handle events internally */
+ protected boolean canEvent() {
+ return true;
+ }
@Override
public JDBCDataStore getDataStore() {
Modified: trunk/modules/unsupported/csv/src/main/java/org/geotools/data/csv/CSVFeatureStore.java
===================================================================
--- trunk/modules/unsupported/csv/src/main/java/org/geotools/data/csv/CSVFeatureStore.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/unsupported/csv/src/main/java/org/geotools/data/csv/CSVFeatureStore.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -29,6 +29,11 @@
public CSVFeatureStore(ContentEntry entry, Query query) {
super(entry,query);
}
+ /** We handle events internally */
+ protected boolean canEvent() {
+ return true;
+ }
+
/**
* Access parent CSVDataStore
*/
Deleted: trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyAttributeWriter.java
===================================================================
--- trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyAttributeWriter.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyAttributeWriter.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -1,152 +0,0 @@
-/*
- * 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.FileWriter;
-import java.io.IOException;
-
-import org.geotools.data.AttributeWriter;
-import org.geotools.data.DataUtilities;
-import org.geotools.util.Converters;
-import org.opengis.feature.simple.SimpleFeatureType;
-import org.opengis.feature.type.AttributeDescriptor;
-
-import com.vividsolutions.jts.geom.Geometry;
-
-/**
- * Simple AttributeWriter that produces Java properties files.
- * <p>
- * This AttributeWriter is part of the geotools2 DataStore tutorial, and should
- * be considered a Toy.
- * </p>
- * <p>
- * The content produced witll start with the property "_" with the value being
- * the typeSpec describing the featureType. Thereafter each line will represent
- * a Features with FeatureID as the property and the attribtues as the value
- * separated by | characters.
- * </p>
- *
- * <pre>
- * <code>
- * _=id:Integer|name:String|geom:Geometry
- * fid1=1|Jody|<i>well known text</i>
- * fid2=2|Brent|<i>well known text</i>
- * fid3=3|Dave|<i>well known text</i>
- * </code>
- * </pre>
- *
- * @author Jody Garnett
- *
- *
- * @source $URL$
- */
-public class PropertyAttributeWriter implements AttributeWriter {
- BufferedWriter writer;
-
- SimpleFeatureType type;
-
- public PropertyAttributeWriter(File file, SimpleFeatureType featureType)
- throws IOException {
- writer = new BufferedWriter(new FileWriter(file));
- type = featureType;
- writer.write("_=");
- writer.write(DataUtilities.spec(type));
- }
-
- public int getAttributeCount() {
- return type.getAttributeCount();
- }
-
- public AttributeDescriptor getAttributeType(int index)
- throws ArrayIndexOutOfBoundsException {
- return type.getDescriptor(index);
- }
- // constructor end
- // next start
- public boolean hasNext() throws IOException {
- return false;
- }
-
- public void next() throws IOException {
- if (writer == null) {
- throw new IOException("Writer has been closed");
- }
- writer.newLine();
- writer.flush();
- }
- // next end
-
- // writeFeatureID start
- public void writeFeatureID(String fid) throws IOException {
- if (writer == null) {
- throw new IOException("Writer has been closed");
- }
- writer.write(fid);
- }
- // writeFeatureID end
-
- // write start
- 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 );
- }
- }
- // write end
-
- // close start
- public void close() throws IOException {
- if (writer == null) {
- throw new IOException("Writer has already been closed");
- }
- writer.close();
- writer = null;
- type = null;
- }
- // close end
- // echoLine start
- public void echoLine(String line) throws IOException {
- if (writer == null) {
- throw new IOException("Writer has been closed");
- }
- if (line == null) {
- return;
- }
- writer.write(line);
- }
- // echoLine end
-}
Modified: trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyFeatureStore.java
===================================================================
--- trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyFeatureStore.java 2011-12-13 11:08:18 UTC (rev 38422)
+++ trunk/modules/unsupported/property-ng/src/main/java/org/geotools/data/property/ng/PropertyFeatureStore.java 2011-12-18 11:54:33 UTC (rev 38423)
@@ -48,7 +48,11 @@
this.store = (PropertyDataStore) entry.getDataStore();
this.typeName = entry.getTypeName();
}
-
+ /** We handle events internally */
+ protected boolean canEvent() {
+ return false;
+ }
+
protected QueryCapabilities buildQueryCapabilities() {
return new QueryCapabilities(){
public boolean isUseProvidedFIDSupported() {
|