DMA Object Model

Introduction

The DMA object model provides a scaleable, robust data model that which allows the integration of a broad range of document management applications and services. Within the context of the DMA model, objects are abstractions of data and methods that operate on this data. This approach provides a uniform programming model which insulates client applications from the implementation details of the underlying document space and allows the same application to operate over document spaces provided by different vendors. This important characteristic of the DMA object model is referred to as separation of interface from implementation.

The principal characteristics of DMA objects are listed below:

DMA Classes

A DMA class is a definition for set of objects having the same supported methods and properties. It should be noted that this use of the term "class" is somewhat different from its usage in other contexts (such as COM or C++) where class signifies implementation. In DMA, class signifies a type of object for which there can be many implementations.

Class Naming

A class is named by one or more globally unique identifiers (GUIDs). The initial identifier is assigned by the original author of the class definition (DMA, in the case of the classes specified in this document). Additional identifiers may be assigned later, with the purpose of creating a common alias identifier applicable to initially distinct classes which have been recognized as being semantically equivalent. This feature is important in operations such as query which can span multiple document spaces. DMA 1.0 does not define mechanisms for alias management, but it is not expected that aliases will be necessary for any of the classes defined by DMA.

It is illegal for two classes of an individual Document Space to have a common alias ID. Alias ID’s for classes and properties are strictly for purposes of metadata unification across distinct Document Spaces when building a merged scope.

It is illegal to simultaneously assign the same ID to both a class and a property, or to both a class and a query operator, etc.

Class Inheritance

DMA supports the definition of a new class by derivation from a single existing class. If a distinct class R derives its definition directly from another class Q then we say that Q is the immediate superclass of R. If Q in turn has immediate superclass P, then both P and Q are superclasses of R. We say that a class Y is a subclass of class X if either X is Y or if X is a superclass of Y. If X is a superclass of Y (and therefore is not Y) then we say that Y is a proper subclass of X. If X is the immediate superclass of Y then Y is an immediate subclass of X. (By definition, an immediate subclass is a proper subclass).

(Note that a class is a subclass of itself, but not a superclass of itself).

An immediate subclass inherits the characteristics of its immediate superclass in the following fashion:

The definition of the subclass may diverge from that of the superclass in the following ways:

The subclass must differ from its superclass in respect of naming. No identifier used to name the subclass may also be an identifier of the immediate superclass, or any of its superclasses.

Multiple (different) subclasses can be derived from single superclass, and each subclass can be further derived from (multiple times), thus creating a hierarchy of increasingly specialized classes. The root of this hierarchical inheritance tree is the DMA base class (dmaClass_DMA), which defines the properties and methods required of every DMA object. The following diagram shows the upper levels of the DMA inheritance tree, with the subclasses grouped into functional areas.

Figure -1 DMA Class Hierarchy

Every DMA object is an instance of exactly one class. However, the object may conform to many class definitions, since it possesses all the properties and supports all the methods required by each successive superclass of its class, all the way up to the base.

Class Metadata

Every DMA object describes the class to which it belongs by means of an object-valued property containing a description of the class.

The metadata object contained in the class description property is itself a DMA object, whose properties define the class. The metadata object includes the following:

Also, since a Class Description object is a DMA object, it belongs to a class (dmaClass_ClassDescription) and has a class description property, and the DMA object contained in that property (a Class Description object for dmaClass_ClassDescription) will have a class description property, and so on. The apparent infinite recursion is broken by the following rule: the class description property of a Class Description object for dmaClass_ClassDescription is null. The following diagram presents (in simplified form) the structure of objects and metadata:

Figure -2 DMA Class and Property Description Classes

The diagram shows an instance of a fictional class Document having four properties: Author, Title, Size and ClassDescription. The value of the ClassDescription property is an object (instance) of class ClassDescription, having three properties: Class described, Property descriptions and ClassDescription. The ClassDescription and PropertyDescription objects shown here are only a partial representation of the actual objects.

In DMA 1.0, the class description does not specify the methods supported by objects of that class. That information is currently given only in this specification, for each well known DMA class. However, based on a priori knowledge of potential methods, COM includes an interface negotiation mechanism which allows runtime determination of the methods supported by a particular object instance.

DMA Properties

Properties are the principal way by which DMA objects expose (via GetProp methods) and allow manipulation of (via PutProp methods) their state. A property is a named value which may be simple or complex in nature. Properties are defined within a class and through inheritance.

Property Datatypes

A DMA property has a specified datatype. DMA allows for properties whose value is a singleton of the specified datatype (a single-valued property) or which contains multiple instances all of the specified datatype (a multi-valued property). DMA does not allow a multi-valued property consisting of heterogeneous datatypes.

The following are the permitted property datatypes:

The DMA methods for accessing property values are strongly typed. There are distinct methods for accessing each property datatype. A multi-valued property must be accessed using the object datatype methods; methods are then applied to the object returned to access to the individual values of the property. The object which represents a multi-valued property can be either a list or an enumeration, both of which are described in detail below.

Object-valued Properties

DMA uses object-valued properties for three distinct purposes, one of which (providing access to the values of a multi-valued property) has already been mentioned. The other two purposes are:

Object-valued properties other than enumerations (whose exceptional behavior is described later) exhibit uniform by reference behavior. The characteristics of this behaviour are described below:

This model depends upon the reference counting mechanism of COM to manage the lifetimes of objects bound to properties, hence its name.

Multi-valued Properties

As mentioned above, there are two types of multi-valued property: list and enumeration. Each type is represented by an object providing methods for accessing the elemental values of the property. The differences between a list and an enumeration are as follows:

DMA defines list object classes (and associated methods for operating on them) for each of the base property datatypes, However, an enumerator class and methods are defined currently only for enumeration of object. DMA does not prescribe when one should be used rather than the other (except as implied by the restrictions and differences noted above), but in general enumerations are preferred where the number of elements could be larger than can be efficiently represented in list form.

Retrieval of a list object representing the value of a multi-valued property is subject to the by reference rules. In addition, for the specific case of a list of objects, each element of the list also obeys the by reference rules. That is, each element independently exhibits a not bound/bound state which results in the same object being returned on each retrieval of the element. In other words, it is as if each element were a separate single-object-valued property (of the list object).

Enumeration properties do not follow the by reference rules. An enumeration property always behaves as if it is in the unbound state. Each invocation of GetProp returns a newly instantiated enumerator object positioned at the beginning of the sequence.

A PutProp call is not allowed on a multi-valued property of either type. Where permitted, modification of a multi-valued property represented by a list is by operations on the list object, not by substitution of a different list object.

Property Naming

Like classes, properties are named by one or more globally unique identifiers. Multiple identifiers are permitted for the same reason as for class identifiers. Property identifiers are scoped relative to the class and are constrained by the rules of inheritance in the following manner: the identifiers for an inherited property must be identical in the subclass and its superclass. However, when the datatype and semantic of the property is the same, DMA allows (even encourages) the same property identifier to be used in classes having no direct inheritance relationship.

A property is accessed by specifying one of its identifiers as a parameter to a GetProp or PutProp call. In addition, since the class description specifies a well-defined ordering of the properties, alternative methods are provided which allow the intended property to be specified by its index in this ordering.

Property Metadata

The properties of a class are described by Property Description metadata objects maintained in an ordered list in a property of the Class Description object for the class.

Each property is characterized by the values of properties attached to its Property Description object, which define:

Property description objects are classified according to the datatype of the property they describe. There is a separate class of description object for integer properties, string properties, etc. All the property description classes are derived from a common superclass (dmaClass_PropertyDescription) which defines the properties common to all the types of property description.

Metadata Spaces

A metadata space is a collection of classes related by inheritance. Concretely, a metadata space is a runtime construct materialized by an entity called the controlling object and represented by connected Class Description objects for the member classes. Every Class Description object is a member of a metadata space.

The defining characteristic of a metadata space is that its member classes form a single-rooted inheritance tree, and that it is closed and fully connected under class hierarchy navigation. This means that given a Class Description object for a class X and a Class Description object for class Y obtained from the SuperclassDescription property of CD(X), one is guaranteed to find, in the ImmediateSubclassDescriptions property of CD(Y) another Class Description object for class X, CD'(X), giving an identical description for X. In addition, given two classes A and B which are members of the metadata space, there exists a navigation path via SuperclassDescription and ImmediateSubclassDescriptions properties from a Class Description object for A to a Class Description object for B, and vice versa.

The rule of closure does not extend to other (indirect) means of navigation between Class Description objects. For example, the following navigational route may lead to an entirely different metadata space: from a Class Description to its list of Property Descriptions and from one of these (an instance of PropertyDescriptionObject) to the ClassDescription for the RequiredClass of that property. Likewise, navigation to the Class Description object of a Class Description.

There are different types of metadata space. Each metadata space contains a subset of the classes defined in this specification, and may contain other (implementation- or end user-defined) classes. Each type of metadata space is characterized by the classes that it must contain. Every metadata space must contain the class of the controlling object. Every metadata space must contain the DMA base class dmaClass_DMA as the root of the inheritance tree. Any metadata space may contain classes that fall outside its required subset, so long as the navigational closure rule is observed.

A metadata space becomes observable when the class description of the controlling object first becomes accessible, and remains observable so long as the controlling object or any instances of member classes generated from the controlling object exist. During a period of continuous observability, the metadata space is static, meaning that no classes are added or removed, no inheritance relationships change and none of the metadata for the member classes changes. This is referred to as "metadata stability".

The following types of metadata spaces can exist:

Instances of these metadata spaces are conceptually distinct.

With the exception of merged scope metadata spaces, every metadata space must preserve the partial inheritance order of all of the DMA-defined classes it contains. This means that if class Q is a subclass of class P in this specification, and both P and Q are present in a metadata space then Q must be a subclass of P in that space, although with possibly more or fewer intervening levels of inheritance (including none).

In a merged scope metadata space, this rule is relaxed for the searchable classes (but only for the searchable classes). This is because a merged scope cannot in general preserve all the partial orderings of this part of the class hierarchies of the component scopes. The merged scope is permitted (but not required) to have the searchable classes appear as immediate subclasses of dmaClass_DMA.

The individual document space metadata and the metadata of a scope object generated from it are in conceptually distinct metadata spaces instead of conceptually being the same metadata space. The document space metadata need not include the query related classes, but the scope metadata must. Conversely, the scope metadata space need not include non-searchable persistable classes, whereas the document space metadata must include such classes. However, this conceptual distinction need not be reflected in actual practice; it is perfectly permissible for a document space and its scope to share a single runtime metadata space.

A query result metadata space is dynamically generated for each query execution. The metadata space for a query result includes only the metadata for one query and no other queries. The metadata space must include the dynamically generated result row class, which must be a subclass of dmaClass_QueryResultRow.

Persistence

Persistent objects are DMA objects which represent and provide means of modifying persistent state of the underlying document space. They operate in a fashion analogous to most editors, otherwise referred to as scratchpad behavior.

When such an object is first instantiated it is loaded with a snapshot of the persistent data, which forms the scratchpad. Methods are then invoked upon the object, performing the intended changes in the state of the scratchpad object, with no immediate effect upon the persistent store. Eventually, the ExecuteChange method can be invoked upon the object causing it reflect the changes back to the persistent store, or the object can be discarded without saving the changes.

The snapshot which is captured in the scratchpad object offers only limited consistency guarantees with respect to the underlying persistent data. Only the single-valued non-object properties of the object are guaranteed to be populated in a consistent fashion. DMA allows multi- and object-valued properties to be evaluated lazily. Thus, the potential exists for such properties to have inconsistencies with respect to each other and to the state of the document space at the time the object was first loaded. Locking mechanisms are provided which allow a fully consistent snapshot and pessimistic protection against concurrent updates. In addition ExecuteChange can be induced to fail if the scratchpad object to which it is applied has been rendered inconsistent as a result of changes made from elsewhere, thereby providing optimistic concurrent protection.

At any instant, there may be many DMA objects in existence. Each such object will reflect, with varying degrees of consistency, the same underlying persistent data. There is no synchronization between these objects, even when they reside in the same process. Each is a completely independent scratchpad, and changes made via one object are not visible to another except by saving of those changes and resynchronizing the objects from the persistent store.

A mechanism is provided which allows changes to a set of objects to be made persistent in one atomic operation. This is referred to as batching rather than as a transaction because of the ACID properties normally expected of a transaction mechanism only the A (for atomic) is provided. (A full transaction mechanism may be defined in a future version of the DMA specification). A batch operation is performed through the ExecuteChanges method of a DocSpace object.

A persistent object may be either dependently- or independently persistent. A dependently persistent object is one which represents sub-structure of a larger independently persistent object. A dependently persistent object does not support the ExecuteChange method; changes to it are made persistent only when ExecuteChange is invoked upon the containing independently persistent object.

An object is independently persistent if and only if it has an OIID (i.e., the OIID property is supported and has a value).

An OIID is a globally unique reference to the persisted state of an object. Through mechanisms described in the Integration section, an OIID can be used to obtain a scratchpad object bound to that persisted state. The OIID is in a sense an address for the independently persistent object and so we sometimes refer to such objects as being addressable.

An object that supports the IdmaConnection interface is an independently persistent object. However, an instance of an independently persistent object is not required to support the IdmaConnection interface (for example, the instance might be read-only).

An independently persistent object supports the Create Pending, Delete Pending, and Update Pending properties.

A dependently persistent object, by definition, does not have and an OIID and therefore cannot be addressed directly. A dependently persistent object can be obtained only from a property of the independently persistent object which contains it (or by a method call on that object). The snapshot principle also applies to dependently persistent object. The object must deliver a consistent snapshot of its single-valued, non-object properties, with the snapshot being taken no later than the time at which the dependent object is bound (per the by reference rules), but can lazily evaluate its multi- and object-valued properties.

A similar principle applies to a list property of a dependent or independently persistent object. A list behaves much like an object having a set of properties all of the same datatype. A non-object list must deliver a consistent snapshot of the list elements, evaluated no later than the time the list object is bound. A list of objects must consistently snapshot sufficient information to be able to deliver the element count and the element objects, although it is not required (per the by reference rules for list of object elements) to snapshot the element objects themselves until they are bound. This permissiveness with respect to the element objects implies that an object may no longer exist in the persistent store at the time an attempt is made to bind it, and therefore it is permitted for the element retrieval to fail.

Methods with Conflicting Intent

As previously described, a scratchpad object accumulates changes that are to be made later to the persistent store. It is possible for the intended operations being accumulated to logically conflict with each other. Any such conflict is resolved as soon as the conflicting method is called as opposed to when the attempt is made to apply the changes to the persistent store.

The methods that prepare the object for subsequent changes to the persistent store are grouped into two categories: primary intentional methods and secondary intentional methods.

Generally, the primary intentional methods logically conflict with each other, and so are mutually exclusive. It is an error to call two different primary intentional methods on the same object before making its changes to the persistent store. The second primary method called returns DMARC_CONFLICTING_OPERATION.

The same primary intentional method may or may not be allowed to be called multiple times before making the changes to the persistent store. What happens when a specific primary intentional method is called multiple times without making the changes to the persistent store between calls is detailed in the description of that method.

The secondary intentional methods do not conflict with the primary intentional methods or with each other.

The primary intentional methods are:

It should be noted that SetDeletePending can be called with DMA_TRUE or DMA_FALSE as a parameter. The value of the Delete Pending property reflects the value passed to the last SetDeletePending call. When the value of Delete Pending is DMA_TRUE, the object will be deleted when the object’s changes are made to the persistent store. When an object is in this state, it conflicts with the other primary intentional methods, and calls on those methods will return DMARC_CONFLICTING_OPERATION. When the value of Delete Pending is DMA_FALSE, there is no conflict between SetDeletePending and the other primary intentional methods.

The secondary intentional methods include:

Locking Model

Locking is a mechanism by which a consistent snapshot of an independently persistent object and its subordinate dependents can be guaranteed.

Locks are owned by DMA COM scratchpad objects, and are placed on their associated persistent object stored in the Document Space. A scratchpad object can own at most one lock on its associated persistent object. Locks are implemented by a Document Space for the persistent objects that are in the custody of that Document Space. A Document Space grants new locks on a persistent object based on the locks that are already placed on that object. The set of methods that a client can perform on a persistent object is constrained by the locks that exist on that object, if any. A lock is considered to be a resource owned by the scratchpad object and should not persist beyond the lifetime of that object. When a document space connection is released or broken, any existing locks that were placed on scratchpad objects obtained via that connection are removed.

Only existing independently persistent objects can be locked. The methods that implement the DMA locking model for persistent objects are ApplyLock, ConnectAndLockObject and RemoveLock. An object that has not yet been made persistent can not be locked until after it has been made persistent. Purely synthetic objects can not be locked.

It is not required to have a lock on a persistent object before modifying its properties or deleting it. However, if there is a lock on a persistent object, and an attempt is made to modify or delete that object, then the modification or delete operation may be disallowed, depending on the type of lock and on which DMA COM object owns the lock.

The locking methods are synchronous, and the operation is resolved before they return to the caller. The ApplyLock and ConnectAndLockObject methods do not block. The ExecuteChange and ExecuteChanges methods have no effect on locks on persistent objects. Thus, these two methods do not cause the placement or removal of locks on persistent objects, with the exception that if they delete a persistent object, any locks placed on it are deleted as well. (Because read locks and existence locks prohibit deletion of the object, and because a write lock precludes other write locks, the deletion will remove the sole write lock on the object (if one exists and the scratchpad object being is used is the one that owns the write lock))

One consequence of the locking model is that locking errors can be returned by a number of different methods, including ExecuteChange and ExecuteChanges.

There are three types of locks: (1) read lock, (2) write lock, and (3) existence lock.

A read lock is compatible with read locks and existence locks, but is not compatible with write locks. Multiple read locks can be placed on a persistent object simultaneously. A write lock cannot be placed on a persistent object that already has a read lock on it. If there is a read lock on a persistent object, that object may not be modified or deleted via any connection, but it may be retrieved via any connection.

An existence lock is compatible with other existence locks, read locks, and write locks. Multiple existence locks can placed on an object simultaneously, along with multiple read locks, or with a single write lock. A write lock can be placed on an object with an existence lock on it. If there is an existence lock on a persistent object, that object may not be deleted via any connection, but it may be modified and retrieved via any connection.

A write lock precludes other write locks and read locks. At most one write lock can be placed on a persistent object, and while it is in effect, no other read or write locks can be placed on that persistent object. If there is a write lock on an object, the object can be modified, or the object can be deleted if there is no existence lock on the object, but only via the scratchpad object that placed the write lock. However, a persistent object can still be retrieved via any document space connection, even if there is a write lock on it.

Any persistent object may be connected to and retrieved, or its properties returned as part of a query, via any document space connection, regardless of the existence of locks on the object or the kinds of those locks.

A distinction must be made between a DMA COM scratchpad object and the underlying persistent object with which it is associated. Some of the properties of a DMA COM object may be synthetic object valued properties. For example, a canned query may be executed in order to instantiate a DMA COM object for the value of such a property. In this case, a change in the value of the synthetic property can result as a side effect of a change to a separate independently persistent object. Locking a persistent object will not prevent this type of change to the values of the synthetic properties of any DMA COM objects with which it is associated.

For example, a document space may implement direct containment such that there is no independently persistable direct containment relationship object – it is purely synthetic. Therefore, the object to be contained has a property that is modified when the contained object is inserted or deleted from a direct container. Locking the object to be contained, therefore, can prevent insertion or deletion of that object into a direct container in such an implementation.

As another example, referential (or direct) containment may be implemented by a particular document space such that neither the object to be contained nor the container object have any properties that are modified when the object to be contained is inserted or deleted from the container . An independently persistable relationship object is the only object created, deleted, or modified in the document space database. In such an implementation, the locking model does not prevent insertions or deletions into referential (or direct) containers.

Similarly, in the case of versioning, if any of the objects involved (i.e., Configuration History, Version Series, Version Description, or DocVersion) are independently persistable (as opposed to being synthetic objects), the locking model can prevent checkout, checkin, etc. by locking the independently persistable objects whose properties are changed as a result of such methods.

Objects and Implementations

The separation of interface from implementation referred to earlier allows the same DMA class of object to be implemented in different ways by different vendors while exhibiting the same behavior (with certain permitted variations described in the Extensibility section below). This allows an application to operate on objects using only the mechanisms defined in this specification, and assures it of being able to accomplish its task regardless of who supplied the implementation.

This principle extends to objects that operate to other objects. When one DMA object operates on another, it must, in general, be able to accomplish its task using only the mechanisms defined in the DMA specification, without any reliance on implementation-specifics. In other words, DMA intends the public interfaces and properties defined in this specification to be adequate for implementing the interoperability guarantees of this specification. Those interoperability guarantees include searching across repositories and the copying of content from one document space into another.

Where this general rule applies, the operand object may be implemented in any fashion consistent with the specification for the class to which the object belongs; in particular the object may be implemented by the client application itself. However, there may be performance advantages in instantiating such objects from the document space or scope to which it is to be delivered, because implementations are free to have optional hidden interfaces to accelerate performance.

However, there are a number of specific cases where this rule does not apply, because the genesis of the operand object (and hence its implementation) is mandated by this specification. In such cases, any attempt to use an object generated in some other way will result in a runtime error. The objects to which this latter mandate applies are the following:

Note that dependently persistent objects are not the subject of any mandate and so follow the general rule. However, a dependently persistent object which is not delivered (via CreateObject or CreateInstance) by the DocSpace in which it is to be made persistent, must in any case be constructed in such a way to conform to the class description of that document space.

Object implementations may cooperate in establishing private mechanisms by which they offer additional functionality or enhanced performance. The only case in which an implementation may depend on those private extensions being available on another object is when the implementation for the object is known through mandate. In such cases, any appropriate implementation technique may be used to access in the private extensions. In all other cases, the private extensions must represented as additional COM interfaces on the object such that their presence or absence can be determined at runtime through COM interface negotiation.

Required and Optional Features

The DMA class hierarchy defined in this specification and the properties specified for those classes are complete for the purpose of providing all the required and optional features currently specified by DMA. However, this does not mean that all these classes and properties must be present in the runtime metadata of every implementation. Indeed, DMA requires that classes and properties which represent optional features that are not implemented be absent from the runtime metadata. This allows a DMA application to determine the presence or absence of those features from the metadata.

The minimum set of classes which must be implemented in order to meet the baseline requirements for a DMA service is specified in the Conformance section, as are the additional classes which must be provided for each optional feature. In general, if circumstances require a particular class to be present in the runtime metadata, then its superclasses (up to and including dmaClass_DMA) must also be present. However, there are two specific cases where this rule does not apply, because the superclasses are representative of optional features:

Note however that if containment (or versioning) is supported for some classes that are specified to be subclasses of Containable (or Versionable), then class Containable (or Versionable) must be present and the partial ordering rule must be observed. This may result in some classes which are not containable (or versionable) appearing as subclasses of Containable (or Versionable). Therefore, determination of whether a particular object is containable (or versionable) must be done by examination of capabilities or property metadata. An IsOfClass test will not suffice.

If circumstances require a class to be omitted from the runtime metadata, then its superclasses up to but not including dmaClass_DMA should also be omitted, unless their presence is required for some other reason. (I.e. that some other subclass is implemented). For example, if containment is not supported and therefore dmaClass_DirectContainmentRelationship and dmaClass_ReferentialContainmentRelationship are omitted, then dmaClass_ContainmentRelationship and dmaClass_Relationship may also be omitted.

The Object Reference section specifies the properties which must be implemented (i.e. must be present in the runtime metadata) for each class, assuming the class itself is implemented. If a property is not required, then it is representative of an optional feature, and should be present or absent according to whether or not the feature is supported for that class. For example:

Note that implementation of an inherited optional property in a particular class does not imply that the property must be present in the metadata for the superclass in which the DMA specification introduces that property. That would imply, for instance, that the OIID property would be required to be present in the runtime metadata for dmaClass_DMA (and hence all classes), completely defeating the purpose of it being optional.

Extensibility

DMA provides several avenues by which a document space vendor can provide variations to and extensions of the behavior defined by this specification.

First, of the classes and properties defined by this specification, only certain characteristics are mandated, with the remainder left to the discretion of the document space. This includes the option to omit certain features and/or properties as well as allowing some variability in the classes and properties which are supported.

Second, a document space may add properties to any of the DMA-defined classes without changing the class identifier. This option is also open to the DMA in future versions of this specification.

Third, objects may be offered with support for additional methods not defined by DMA. This option is of lesser utility insofar as interoperability is concerned since DMA objects are not self-describing with respect to methods.

Fourth, any of the DMA-defined classes may be subclassed. This is mostly likely to be done at the leaves of the inheritance tree and in particular to the DocVersion class, but is not restricted to this. Included in this option is the ability to introduce new intermediate classes into the DMA inheritance hierarchy, so long as the partial ordering of existing classes is preserved. Subclassing the DMA leaf property classes is the most highly preferred method of extending DMA.

Fifth and last, a document space may offer additional query operators and collating sequences beyond the well known sets defined in this specification.

A document space vendor may also offer extensibility in any of the forms described above as an end user customization feature. Mechanisms for such customization are not defined by the DMA 1.0 specification. Adding properties and classes is preferred over adding interfaces and methods. Additional well known query operators, well known collating sequences, and well known properties may be added to the DMA specification in the future

Evolution of Persistent Metadata

The metadata in the persistent store of the document space may evolve over time. The metadata can be changed off line (i.e., when no DMA clients have valid connections to the document space), and, some systems may also allow it to be changed on line (i.e., when there is at least one DMA client with a valid connection to the document space).

When the persistent metadata is changed off line, the expected behavior will occur after the change. If the change is upward compatible, DMA clients will continue to operate as before the change. If the change is not upward compatible, some problems may occur in DMA clients that were previously operating correctly.

When the persistent metadata is changed on line, then DMA clients that are active at the time may subsequently receive the error code DMARC_STALE_METADATA for certain methods. That is because the client’s metadata is stable, and so does not match (to some degree) the modified metadata in the persistent store.

The key benefit of metadata stability is that the client can count on information derived from the metadata remaining usable without reconsulting the metadata. A DMA application is free to cache information and to carry derived information in its operations with the assurance that the metadata space will not have changed.

The metadata mismatch may or may not matter when a particular query or update is attempted on the persistent store of the document space. If the metadata mismatch doesn’t matter for the operation at hand, the document space implementation may choose to attempt to complete operation and to not return the DMARC_STALE_METADATA error code, or it can return the error without attempting to see if the operation can proceed. If the mismatch does matter, the DMARC_STALE_METADATA error code must be returned.

The reference sections of this specification define which methods are permitted to return DMARC_STALE_METADATA. The general principle is that only methods which bind or modify a persistent object may return the error. Methods which navigate the client's (stable) copy of the metadata or operate on existing scratchpad objects may not return the error.

Document Space Connections

The document space object has a logical connection to the persistent store of the document space. In a distributed system, this connection is implemented on top of a conceptual network connection between the host on which the DMA client runs, and the host on which the persistent store is resident. Some document spaces will require that the client be authenticated before the logical connection is fully operative. Objects created from the document space (e.g., an object that is a subclass of DocVersion) exploit the logical connection of the document space object (for example, by calling IdmaConnection:: ExecuteChange).

The logical connection between a document space object and the persistent store can be broken by calling IdmaDocSpace::ExecuteDisconnect. Once the logical connection to the persistent store is broken, methods on objects that need that logical connection (e.g., ExecuteChange) return DMARC_DISCONECTED errors permanently.

The document space object’s conceptual network connection can be interrupted, give errors, or be broken. In such a case, DMARC_NETWORK_ERROR or DMARC_LOST_CONNECTION might be returned. In addition, platform specific error codes might be returned. The DMARC_NETWORK_ERROR error code gives no information as to whether a subsequent retry might succeed. In contrast, the DMARC_LOST_CONNECTION error code guarantees that the document space connection has become permanently unavailable.

When initially attempting to make a network connection, DMARC_NETWORK_UNAVAILABLE may be returned