ArcFM Desktop Developer Guide
Autoupdater Framework

Resource Center Home

1. Overview

This technical white paper provides an overview of the internals of the ArcFM Autoupdater framework. It is written for business partners, clients, or other parties interested in learning more about how autoupdaters work. This document assumes that the reader is familiar with the use and creation of autoupdaters, as described in the ArcFM Solution documentation.

2. The ArcObjects Editing Events Framework

An understanding of the ArcObjects edit events framework is necessary before learning how ArcFM leverages this framework.

ArcObjects provides three kinds of editing events: row events, class events, and editor events.

2.1 RowEvents

Row events, the first set of editing events that gets fired, are not actually events at all. When a row object is edited, the object checks itself to see if it implements the IRowEvents or IFeatureEvents interfaces. If the interface exists, the appropriate routine on those interfaces is called.

For example, if a row is updated by a call to IRow::Store(), the implementation of Store() will call IRowEvents::OnChanged(), if this row implements the IRowEvents interface.

The IRowEvents interface is implemented by creating a "custom GeoObject" that uses COM aggregation to wrap the appropriate Esri object. ArcFM objects are implemented as custom GeoObjects.

More recent Esri literature refers to "custom GeoObjects" as "custom features."

This table explains the Esri method calls that generate calls to row "events":

Esri Edit Method

Row Event

ITable::CreateRow

IFeatureClass::CreateFeature

IRowEvents::OnNew

IRow::Store

IRowEvents::OnChanged

IRow::Delete

IRowEvents::OnDelete

IFeatureEdit::Split

IFeatureEvents::OnSplit

Remember, of course, that many other Esri calls resolve down to a call to one of these routines.

Note that these row event calls are made during the call to the corresponding Esri edit method. The call has not finished, and returning an error code from the row event will cause the caller to fail with the same error code.

There are other row events in addition to the ones described above. IRowEvents::OnInitialize(), IRowEvents::OnValidate(), and IFeatureEvents::InitShape() are not used by the ArcFM Autoupdater framework. IRowEvents::OnMerge() is not implemented by Esri.

2.2 Object Class Events

The second type of editing events supported by ArcObjects are object class events. These are true events, and are described below:

Esri Edit Method

Object Class Event

ITable::CreateRow

IFeatureClass::CreateFeature

IObjectClassEvents::OnCreate

IRow::Store

IObjectClassEvents::OnChange

As with row events, these object class event calls are made during the call to the corresponding Esri edit method. The call has not finished, and returning an error code from the class event will cause the caller to fail with the same error code.

There are two ways to respond to object class events. The easiest way is to implement a custom class extension. This is not required, however. It is also possible to listen to object class events directly. ArcObjects even includes an ObjectClassEvents helper class to make this possible with Visual Basic. One notable component that listens to ObjectClassEvents is the Esri Object Editor extension, which is described in more detail below. It is worth noting that if multiple clients listen to ObjectClassEvents, the order that these clients receive these events is indeterminate.

A close look at the Geodatabase Object Model will reveal more interfaces on class extensions, namely IRelatedObjectClassEvents, IRelatedObjectClassEvents2, and IConfirmSendRealtedObjectEvents. Depending on how your relationship classes are configured in ArcCatalog, these can generate additional events. ArcFM does not currently use these interfaces.

2.3 EditorEvents

Finally, there is a third kind of editing event supported by ArcObjects. These are also true events, generated by the Esri Object Editor class extension. These are typically implemented by creating an Editor extension (an object that supports IExtension and is registered in the “Esri Editor Extensions” COM category).

 

Esri Edit Method

Editor Event

ITable::CreateRow

IFeatureClass:CreateFeature

IEditEvents::OnCreateFeature

IRow::Store

IEditEvents::OnChangeFeature

IRow::Delete

IEditEvents::OnDeleteFeature

Unfortunately, due to a bug in ArcObjects, returning an error code from the class event will not cause the caller to fail (the error code is not being propagated correctly). The effect of this is that you cannot cause the edit to fail while processing an Editor event.

It is worth noting that Editor Events are really just Object Class Events, repropagated by the Esri Object Editor. Obviously, this means that editor events require the Esri Object Editor, which in turn requires ArcMap. This means that an ArcObjects application that does not require ArcMap will not generate editor events. This kind of application, although possible now, will become far more prevalent with ArcGIS Engine 9.0 and ArcGIS Server 9.0.

It is worth noting, that if multiple clients listen to Editor events, the order that these clients receive these events is indeterminate.

2.4 Esri Event Summary

Here is a summary of the different events that are fired by ArcObjects, and the order in which they occur.

  1. Row Events are fired on custom GeoObjects.
  2. Object Class Events are fired on custom class extensions.
  3. Object Class Events are fired on other components that listen to them, in an indeterminate order. If ArcMap is running, one of these components is the Esri Object Editor, which propagates them as Editor Events (and if multiple clients are listening to Editor Events, the order is indeterminate).

 

3. How the Autoupdater Works

The Autoupdater is 2 in a COM object called MMAutoUpdater. This object is both a COM singleton and an ArcMap Editor extension.

Autoupdaters work differently, depending on whether ArcFM or Esri objects are used.

From the perspective of the Autoupdater framework, ArcFM and Designer objects work the same way. All references to “ArcFM Objects” in this document apply equally to Designer objects.

3.1 Row Events and the Autoupdater

Our ArcFM objects "listen" to Row events by implementing the IRowEvents and IFeatureEvents interfaces, as described in section 2.1 above. In response to these events, methods are called on the MMAutoUpdater object. These methods fire the assigned autoupdaters, as described in section 3.3.

Note that because our ArcFM objects initiate the Autoupdater call, autoupdaters will always fire, even if ArcMap is not running. Because they are called with Row events, returning an error code can prevent the edit from taking place.

3.2 Editor Events and the Autoupdater

In addition to Row Events, the MMAutoUpdater object listens to Editor events, as described in section 2.3 above. If the MMAutoUpdater receives an editor event that involves an ArcFM object, it disregards it, since it will have already received an appropriate Row event. However, if the MMAutoUpdater receives an editor event regarding an Esri object, we fire the assigned autoupdaters as described in section 3.3.

Remember that Editor Events cannot prevent the edit from taking place. The practical effect of this is that returning MM_E_CANCELEDIT has no effect with Esri objects.

3.3 Firing Autoupdaters

When the Autoupdater is fired, Attribute autoupdaters are fired first. These are fired in the order that the fields are listed in the ArcFM Properties for that feature class. If all of these autoupdaters succeed, the Special autoupdaters are fired.

 

4. Relationship Events and the Autoupdater

What about edits to Relationships? The answer, of course, is another kind of event, a relationship class event.

Esri Edit Method

Relationship Class Event

IRelationshipClass::CreateRelationship

IRelationshipClassEvents::OnCreate

IRow::Store

IRelationshipClassEvents::OnChange

IRelationshipClass::DeleteRelationship

IRelationshipClassEvents::OnDelete

The IRelationshipClass::DeleteRelationshipsForObject() and IRelationshipClass::DeleteRelationshipsForObjectSet() generate one relationship class event for every relationship involved, of course.

ArcFM listens to Relationship Class Events through a geodatabase class extension that resides on ArcFM Objects. This class extension calls the Autoupdater framework, which fires the assigned relationship autoupdater strategies.

Remember that attributed relationships are a special kind of Esri Relationship that stores additional fields. These Attributed Relationship objects implement IRow, and editing the additional fields causes IRow::Store to get called.

4.1 When Do Relationship Class Events Get Fired?

Obviously, they get fired when the relationship is edited. Note that CreateRelationship is called after the two objects to be related are created, and DeleteRelationship is called before the related objects are deleted. Of course, you can relate and unrelate objects without creating or deleting the objects that make up the relationship.

This order must be kept in mind when writing autoupdaters. In a Create autoupdater, there is no sense in looking for related objects, because the relationships have not been built yet. Likewise, the relationships have already been destroyed by the time Delete autoupdater gets called.

 

5. Advanced Splitting Information

5.1 Esri Relationship Split Policies

When a network edge is split, a decision has to be made what to do with the related objects. This is defined by a relationship split policy, as described in the table below:

Relationship Split Policy

Description

esriRSPUseDefault

The default behavior, which is EsriRSPPreserveOnLargest for simple relationships and esriRSPDeleteParts for composite relationships

esriRSPPreserveOnLargest

Preserve related objects and create a relationship with the Feature with the largest part of the split geometry.

esriRSPPreserveOnSmallest

Preserve related objects and create a relationship with the Feature with the smallest part of the split geometry.

esriRSPPreserveOnAll

Preserve related objects and create a relationship with both Features. This option is not valid with relationships with 1..1 cardinality or composite relationships.

esriRSPDeleteRelationship

Delete the relationship.

esriRSPDeleteParts

Delete the related objects.

5.2 BeforeSplit and AfterSplit Autoupdaters

5.2.1 The ConductorInfo Problem

In the ArcFM Electric data model, conductors are modeled as network edges, while characteristics of the individual wires are modeled as related objects (ConductorInfo). When a conductor is split, the desired behavior is that the related ConductorInfo objects are duplicated. In other words, for each ConductorInfo record related to the original edge, there should be a ConductorInfo record (with identical attributes) related to each of the resulting edges after the split.

A quick perusal of the Relationship Split Policy table above will reveal that there is no mechanism built-in to ArcObjects to achieve this behavior.

5.2.2 Solving the ConductorInfo Problem

Schneider Electric solved this problem in a very complex way. What we did was overload the Split() method in our ArcFM objects. The overloaded behavior is to generate a pseudo-event for BeforeSplit and AfterSplit. The program logic is as follows:

  1. Call the BeforeSplit autoupdater. The BeforeSplit autoupdater that comes with the product unrelates the related objects from the conductor, and stores them on the ArcFM feature using a special interface.
  2. Call the Split() method on the aggregated Esri feature. Note that this will call the OnSplit Row event.
  3. Call the AfterSplit autoupdater on each resulting edge. The AfterSplit autoupdater that comes with the product looks at the cache of objects that were stored in the BeforeSplit autoupdater and copies them, taking these copies and related them to the new edge.
  4. The ArcFM feature deletes the original related objects.

5.2.3 Using BeforeSplit and AfterSplit for Other Purposes

As you can probably imagine from reading the above section, the logic for the BeforeSplit/AfterSplit is a very complex, highly-orchestrated set of code. In addition to the complexity described above, Designer adds additional logic to replicate GUs and CUs in the design tree.

The Esri Geodatabase team was heavily consulted while building the above code. They agree with us that this is not the best way to solve this problem. We have had several conversations with them in an attempt to convince them to create a new split policy that will copy related objects automatically. If this happens, we will probably drop support for the BeforeSplit and AfterSplit events.

For this reason, we recommend that any developer who wishes to make use of these events for their own purposes contact the Schneider Electric product team before doing so.

 

6. Cautions

6.1 Problems with MM_E_CANCELEDIT

Returning MM_E_CANCELEDIT from an autoupdater object is a useful tool to prevent a feature from being edited. It’s important to understand how this works.

  1. The autoupdater strategy returns MM_E_CANCELEDIT.
  2. The Autoupdater framework receives this error code and returns it.
  3. The ArcFM object receives this error and returns the same error code from the calling Row event routine.
  4. The appropriate Esri edit method (CreateRow, CreateFeature, Store, or Delete) returns this same error code.

At the end of the chain, the code that called the Esri edit method receives an MM_E_CANCELEDIT error code. The ArcFM Solution editing tools know that this is a "special" error, and silently fail.

Regrettably, the ArcMap editing tools (e.g., the Move tool), with no knowledge of our framework, usually respond with an error message to the user. End-users are often confused by this message, but there is nothing that Schneider Electric can do about this. We have repeatedly tried to convince Esri to provide us with a special error code that is silently ignored by the ArcMap editing tools, but they have not yet agreed to implement this functionality.

6.2 Edit Operations

Edit Operations are used by ArcObjects to define a set of edits that can be undone/redone as a group. They are also used to define editing states in a versioned geodatabase. Edit Operations are created with a call to StartOperation. They can be successfully committed with a call to StopOperation or rolled by a call to AbortOperation. It is extremely important to realize that calls to these routines cannot be nested. In other words, each and every call to StartOperation must be paired with one and only one call to either StopOperation or AbortOperation. In addition, it is not possible to tell whether or not an operation has already been started.

Typically, these restrictions are not a problem. An editing tool, such as the ArcFM Attribute Editor or the ArcMap Delete tool will use the following program flow:

  1. Call StartOperation.
  2. Make a series of edits using the Esri edit methods (Create Row, Store, et.al.).
  3. Conclude with a call to StopOperation if the edits were successful or AbortOperation if the edits were not.

The only real problem comes about if an autoupdater tries to call AbortOperation itself, usually in a misguided attempt to abort the edit. As you can see above, however, this will result in mismatched edit operation calls. The Esri Geodatabase team has warned us that this can corrupt the operation stack. This is turn can corrupt the geometric network, or the version state tree. Worse yet, the code can appear to work, but can be silently corrupting data in the background. Under no circumstances should you call StartOperation, StopOperation, or AbortOperation in an autoupdater.

 

 

 


Send Comment to ArcFMdocumentation@schneider-electric.com