[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]
Subject: AW: [sdo] ISSUE 160: ChangeSummary and OrphanHolders, proposed resolution
4.3 ChangeSummary
A ChangeSummary provides access to the changes made to the
DataObjects in a data graph, comparing the data graph’s “before” state to its
“after” state. The “before” state is the state of the data graph at
the time when logging was activated. If logging is no longer active, the “after”
state is the state of the graph when logging was deactivated. This means
that only changes that were made up to the point when logging was deactivated
are included in the ChangeSummary. Otherwise, the ChangeSummary includes all
changes up to the point at which the it is interrogated. The
ChangeSummary contains only net changes, transient values that are assigned to
properties after logging begins, but which are overwritten before logging is
deactivated are not visible throught the change summary. Although change
information is only gathered when logging is on, the ChangeSummary can be
queried whether logging is on or off. All of the information returned is
read-only.
The ChangeSummary interface has methods that:
4.3.1 Starting and Stopping Change Logging
ChangeSummary.beginLogging() clears
the ChangeSummary’s list of changed DataObjects and starts change logging.
ChangeSummary.endLogging() stops change logging. ChangeSummary.undoChanges()
restores the data graph to its state when logging began.
ChangeSummary.undoChanges() also clears the log, but does not affect
isLogging().
NOTE: The beginLogging(), endLogging() and undoChanges() methods are intended primarily for the use of service implementations since services define how the processing of a ChangeSummary relates to external resources. Making changes that are not captured in the ChangeSummary may cause services that drive updates from a ChangeSummary to act on incomplete information.
4.3.2 ChangeSummary Root
ChangeSummaries become associated with
DataObjects when the DataObject includes a Property with type
ChangeSummaryType. The ChangeSummary root is the DataObject having the
ChangeSummary property. ChangeSummary.getRootObject() MUST return the
ChangeSummary root. Calling DataObject.getChangeSummary() on the
ChangeSummary root, or on any DataObject contained, directly or indirectly, by
the ChangeSummary root, MUST return the same ChangeSummary object. It MUST
also be possible to retrieve this object using
DataObject.get(“changeSummaryProperty”) where “changeSummaryProperty” is the
name of a property whose Type is ChangeSummaryType. The following rules
and restrictions apply to ChangeSummary properties:
4.3.3 ChangeSummary Scope
The scope of a ChangeSummary is defined as the
set of DataObjects reachable from the ChangeSummary root either through
containment or over any orphanHolder properties. In other words the
scope of the change summary is the same set of DataObjects that would be in the
sub-tree whose root node is ChangeSummary root, if the graph were serialized to
XML
DataObjects that were in the ChangeSummary scope when logging was activated but are not in the scope when logging was deactivated (or when ChangeSummary.getChangedObjects() was called, if logging is still active) and which are not themselves contained by a deleted DataObject MUST be appear in the ChangeSummary as deleted. DataObjects that were not in the ChangeSummary scope when logging was activated , but are in scope when logging was deactivated (or when ChangeSummary.getChangedObjects() was called, if logging is still active) and which are not themselves contained by a created DataObject MUST be appear in the ChangeSummary as created. Other DataObjects within the ChangeSummary scope whose property values changed during the time that logging was activated MUST appear in the ChangeSummary as modified.
4.3.4 OrphanHolder Properties
Although orphanHolder properties play a role in
determining the scope of the ChangeSummary, changes to the orphanHolder
properties themselves are not tracked. If the only change to the
ChangeSummary root is to the contents of its orphanHolder properties, the object
itself MUST NOT be contained in the ChangeSummary as a modified.
OrphanHolder properties MUST NOT appear
in the getOldValues, getOldSequence lists.
The following restrictions apply to the use of orphanHolder
properties together with ChangeSummaries.
1. If an orphan DataObject is referenced from within the scope of a ChangeSummary, and if an object with a matching orphanHolder property is contained, either directly then the object is in scope of the ChangeSummary. When the change summary root is serialized using XMLHelper.save, then the orphan DataObject must be serialized as being “contained” by the ChangeSummary root’s orphanHolder property.
2. All orphanHolders associated with the ChangeSummary root or any DataObjects contained, directly or indirectly by the ChangeSummary root MUST be considered in determining the scope.
3. Orphan Holder properties are intended to be declared on envelopes and other technical DataObjects, rather than on DataObjects that are used to represent business entities. Defining orphanHolder properties on DataObjects that themselves are orphans, or that are contained by orphans, is not allowed, and MAY be ignored by implementations.
4. ChangeSummary properties are intended to be declared on envelopes and other technical DataObjects, rather than on DataObjects that are used to represent business entities. Defining ChangeSummary on DataObjects that themselves are orphans, or that are contained by orphans is not allowed, and MAY be ignored by implementations.
4.3.5 Old Values
A List of old values can be retrieved using the
getOldValues(DataObject dataObject) method. The order of old values returned is
implementation dependent. For a deleted DataObject, the old values List
contains all the properties of the DataObject. For a DataObject that has been
modified, the old values List consists of the modified properties only. For a
DataObject that has not been deleted or modified, the List of old values is
empty.
Individual languages MAY return a list of changed properties or a list of objects which contain the old value, the property, and other information if desired. If a list of objects is returned, then getOldValue and isOldSet are methods on the returned objects.
4.3.6 Sequenced DataObject
getOldSequence(DataObject dataObject) returns
the entire value of a DataObject’s Sequence, at the point when logging began.
This return value can be null. If DataObject.getSequence() returns null then
getOldSequence(DataObject dataObject) will return null.
4.3.7 Serialization and Deserialization
When a ChangeSummary is deserialized,
the logging state will be on if a <changeSummary> element is present in
the XML unless the changeSummary marks logging as off. A serializer must produce
a <changeSummary> element in the XML if either of the following conditions
applies:
The state of logging is recorded in the logging attribute of the changeSummary element.
The serialization of a ChangeSummary includes enough information to reconstruct the original state of all DataObjects in its scope, at the point when logging was turned on. Each individual object removed from the data graph must be recorded in the ChangeSummary serialization in order to perform this reconstruction. The create attribute labels DataObjects currently in the data graph that were not present when logging started, and the delete attribute labels objects contained in the change summary that are no longer in the data graph. Labels are space-separated lists of either IDs, if available, or XPath expressions.
The contents of a ChangeSummary element are either deep copies of the objects at the point they were deleted, or a prototype of an object that has had only data type changes, with values for the properties that have changed value.
4.3.8 ChangeSummary Interface
The type returned by getOldValue, and the types in the List returned by getOldValues is implementation language dependent.
_______________________________________________________________________________________________________________
6.4 SDO Type and Property constraints
There are several restrictions on SDO
Types and Properties. These restrictions ensure Types and Properties for
DataObjects are consistent with their API behavior. Behavior of
ChangeSummaryType Properties is defined.
Instances of Types with dataType=false
must implement the DataObject interface.
Values of bidirectional Properties with
type.dataType=false and many=true must be unique objects within the same
list.
Values of
Properties with type.dataType=false and many=true cannot contain
null.
Property.containment has no effect unless
type.dataType=false.
Property.default!=null requires type.dataType=true and
many=false
Types with
dataType=true cannot contain properties, and must have open=false and
sequenced=false.
Type.dataType and sequenced must have the same value as their base Types'
dataType and sequenced.
Type.open may only be false when the base Types' open are also
false.
An implementation
is not required to modify pre-existing types when derived types are
defined.
Properties that
are bidirectional require type.dataType=false
Properties that are bidirectional require that
no more than one end has containment=true
Properties that are bidirectional require that both ends have
the same value for readOnly
Properties that are bidirectional with containment require that the
non-containment Property has many=false.
Names and aliasNames must all be unique within
Type.getProperties()
_______________________________________________________________________________________________________________
11.2
Inclusion of Orphaned Objects
As discussed in section 4.3.3, if the ChangeSummary root
contains orphanHolder properties, the orphaned objects that are associated with
these holders are also in the scope of the ChangeSummary.
As discussed in section 4.3.4, changes
to the orphanHolder properties themselves are not tracked as
modifications.
This has the consequence that modified and deleted orphans always appear
as top level elements in the changeSummary XML. Other than this, there are
no special rules for the serialization the changes associated with orphaned
DataObjects.
11.3 Example Use of ChangeSummary on a
DataObject
We begin
with a model that is specified without a containment structure. In this
example, we use a simple model of an organization, with types representing the
company, its departments and their employees. For clarity, we specify the
model using XSD:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://sdo.example"
xmlns:tns="http://sdo.example" xmlns:sdox="commonj.sdo/xml">
<element name="Company" type="tns:Company" />
<complexType name="Company">
<sequence>
<element name="department" type="string" sdox:propertyType="tns:Department"
minOccurs="0" maxOccurs="unbounded"
/>
</sequence>
<attribute name="name" type="string" sdox:key="true"
/>
</complexType>
<complexType name="Department">
<sequence>
<element name="employee" type="string" sdox:propertyType="tns:Employee"
minOccurs="0" maxOccurs="unbounded"
/>
</sequence>
<attribute name="name" type="string" sdox:key="true"
/>
</complexType>
<complexType name="Employee">
<attribute name="name" type="string" sdox:key="true"
/>
<attribute name="salary" type="int" />
</complexType>
</schema>
Let us suppose that the client receives the following document from the server.
<?xml version="1.0" encoding="UTF-8"?>
<sdo:datagraph xmlns:sdo="commonj.sdo"
xmlns:ex="http://sdo.example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<changeSummary logging="true"/>
<ex:Company name="Acme">
<department>Sales</department>
<department>Manufacturing</department>
</ex:Company>
<orphanHolder xsi:type="ex:Department" name="Sales">
<employee>Ron</employee>
<employee>Stefan</employee>
</orphanHolder>
<orphanHolder xsi:type="ex:Department" name="Manufacturing">
<employee>Stefan</employee>
<employee>Ulf</employee>
</orphanHolder>
<orphanHolder xsi:type="ex:Employee"
name="Ron"
salary="2"/>
<orphanHolder xsi:type="ex:Employee"
name="Ulf"
salary="2"/>
<orphanHolder xsi:type="ex:Employee"
name="Stefan"
salary="2"/>
</sdo:datagraph>
After deleting the "Sales" department, changing a salary and adding a new employee to Manufacturing, calling XMLHelper.save returns the following document:
<?xml version="1.0" encoding="UTF-8"?>
<sdo:datagraph xmlns:sdo="commonj.sdo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ex="http://sdo.example">
<changeSummary create="#/orphanHolder.3"
delete="#/changeSummary/orphanHolder.2
#/changeSummary/orphanHolder.3">
<ex:Company
xsi:type="ex:Company"
sdo:ref="Acme">
<department
sdo:ref="Sales"></department>
<department
sdo:ref="Manufacturing"></department>
</ex:Company>
<orphanHolder xsi:type="ex:Department" sdo:ref="Manufacturing">
<employee
sdo:ref="Stefan"></employee>
<employee
sdo:ref="Ulf"></employee>
</orphanHolder>
<orphanHolder xsi:type="ex:Employee"
sdo:ref="Stefan"
salary="2"></orphanHolder>
<orphanHolder xsi:type="ex:Employee"
name="Ron"
salary="2"></orphanHolder>
<orphanHolder xsi:type="ex:Department" name="Sales">
<employee>Ron</employee>
<employee>Stefan</employee>
</orphanHolder>
</changeSummary>
<orphanHolder xsi:type="ex:Department" name="Manufacturing">
<employee>Stefan</employee>
<employee>Ulf</employee>
<employee>Frank</employee>
</orphanHolder>
<orphanHolder xsi:type="ex:Employee"
name="Stefan"
salary="3"></orphanHolder>
<orphanHolder xsi:type="ex:Employee"
name="Ulf"
salary="2"></orphanHolder>
<orphanHolder xsi:type="ex:Employee"
name="Frank"
salary="2"></orphanHolder>
<ex:Company name="Acme">
<department>Manufacturing</department>
</ex:Company>
</sdo:datagraph>
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]