We need feature events to draw changes as they occur, and keep caches in sync.
What changed where
This page represents the current plan; for discussion please check the tracker link above.
FeatureEvents have long been something missed in the GeoTools library; the uDig project has hacked a few DataStores into submission way back in GeoTools 2.2. Now that we have updated to GeoTools trunk it is time to talk about what we have learned and see what can be cleaned up. Conversely FeatureEvents have not been implemented by the various DataStore implementations; in part that is probably due to a lack of clarity and available test cases; we need to take implementation experience into account and provide an event notification system that can be implemented.
There are several "feature event" notification things around:
- FeatureCollection add/remove CollectionListener
- CollectionEvent tracks FEATURES_ADDED / FEATURES_REMOVED / FEATURES_CHANGED and holds an array of changed features
- FeatureSource add/remove FeatureListener
- FeatureEvent tracks FEATURES_ADDED / FEATURES_REMOVED / FEATURES_CHANGED and holds bounds
There are two other input reference points around the functionality of the "commit" step:
- The FIDs created by addFeatures are often temporary; until the commit() method is called. WFSDataStore has taken to maintaining a history of all temporary FeatureIds handed out, it creates a mapping from temporary Id to a real Id during the commit, and then uses this mapping to preprocess all incoming FidFilters into a form understood by the web feature server. Wow.
- The revised datastore api figured out for GeoAPI forced the commit step to return the set of added FeatureIds in order to handle the same problem
- DataStoreEvents were added as part of one of the many catalog proposal in the hopes of noticing when the bounds were changed on the data store.
- During the code sprint a lot of the ReferencedEnvelope changes were centred on building up the bounds for a FeatureEvent; this code looked really troubled to start with and the result had been cut and pasted everywhere.
- FeatureCollection is gradually being punted in the direction of a data result rather than a read/write API
- FeatureListenerManager already gathers up the hard work of handling events on different transactions; it is a utility class used by DataStore implementors as far as I know nobody has implemented events without using this class.
- The feature added/removed/changed events are documented to be performed at each FeatureWriter.next(), some implementors are using FeatureWriter.write().
- It would be easier for listeners if the changes were batched up and sent once. On FeatureWriter.close() and on FeatureStore.add/remove/modifyFeatures. That is a single event shall be thrown once the add/remove/modifyFeatures method did its work.
Distractions, Observations and Complaints:
- GR: I'd actually would like to get rid of FeatureWriter as a first class citizen.
- GR: DataStore.getFeatureWriter(...) is quite missplaced, if should ever have to exist, it should be part of the FeatureStore interface
- For the listener (ie uDig or a cache implementation) the FeatureEvent will capture a Filter and optional bounds. This is more efficient than an array of SimpleFeature (which would prove fatal if we ever did it). We will provide a NullObject for the bounding box that represents everything (to prevent client code from continuing to do null checks) on bounds.
- For the data store implementor we will make the FeatureEventImpl object a lot smarter; it will have methods for addFeature( SimpleFeature ) so that you no longer have to manage ReferenceEnvelope madness yourself. You can either make these events and fire them on every change; or go through your loop and build up an event to fire at the end.
- For the data store implementor we will make the FeatureEventImpl do whatever is needed for your "commit" cycle; as long as the event is keeping a Filter we should be able to handle the case where a Id filter of FeatureId is updated as actual identifiers are acquired during commit. Since FeatureId is an object rather than a String we can do this without violating encapsulations. This change is limited to the
FeatureListenerManagerclass and may get better over time; we don't need to get it perfect right off to have a benifit.
- For the data store implementor we will ask them to fire an event on FeatureWriter.close(); rather than next() or write(). They can create a FeatureEvent at the start of their FeatureWriter and add to it as they iterate.
- For the data store implementor we will ask for a single event for each add / remove / modifyFeatures FeatureStore call (most do this already).
The window for feedback on this proposal has closed, the proposal has been accepted by default.
Initial discussion as part of an IRC meeting was mostly in agreement. Justin made the interesting observation that only one of the changes is significant to client code:
Voting is open:
dynamictasklist: task list macros declared inside wiki-markup macros are not supported
This section is used to make sure your proposal is complete (did you remember documentation?) and has enough paid or volunteer time lined up to be a success
- Deprecate CollectionListener / CollectionEvent - asking people to listen to the FeatureSource instead
- Introduce RefernecedEnvelope.EVERYTHING
- Add Filter to FeatureEvent
- Add Filter and Bounds "building" methods to FeatureEvent( update: Implemented as BatchFeatureEvent)
- Update the DataStore Tutorial section on FeatureEvents based on the ArcSDE experience
- Provide an example of using a listening with FeatureEvents in the user guide
describe subject is being changed
Deprecate code that is orphaned (maybe done in GeoTools 2.4?):
Expand ReferencedEnvelope to include the definition of everything:
Add helper methods to FeatureEvent so DataStore implementors do not have to work so hard to build up a good change notification:
Subclass to provide batch notification on Commit / Rollback. This is used by FeatureListenerManager to report a bit more detail on transaction commit() and rollback(). Right now these changes show up as a change event with no known bounds.
With the following changes to javadocs documenting expected behaviour:
We also need to allow our FeatureIdImpl to be "updated" during the commit:
There has been little documentation thus far around the behaviour of events during editing; so in that sense our work is easy.