OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

sdo message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: Re: [sdo] ISSUE 160: ChangeSummary and OrphanHolders, proposed resolution


Title: ISSUE 160: ChangeSummary and OrphanHolders, proposed resolution
Hi Ron,

How does the following use case apply to ChangeSummary and OrphanHolder properties?

Consider the following type model:

    A (with ChangeSummary) --containment --> B
    B --non-containment--> A (with orphan property)

Use them to create a data graph:

    aDO = dataFactory.create("urn:example", "A");
    bDO = aDO.createDataObject("b");
    aDO.getChangeSummary().beginLogging();
    aDO.set("name", "a");
    bDO.set("name", "b");

When aDO is marshalled (as the root) to XML the change summary section will include the changes made to both aDO & bDO.  If bDO is marshalled (as the root) to XML which objects are represented in the ChangeSummary?
  1. Both aDO & bDO
  2. Only aDO as bDO is outside the scope of the ChangeSummary for this XML representation
  3. bDO is an invalid root because it has a containment relationship to aDO

-Blaise


Barack, Ron wrote:
7C3EF93EEBC6EB4A8B4470853DE86566DEEDF2@dewdfe18.wdf.sap.corp" type="cite">

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:

    • Activate and deactivate logging.
    • Restore a tree of DataObjects to the state it was in when logging began and clear the log.
    • Query the logging status.
    • Get the ChangeSummary’s root DataObject.
    • Get the list of changed DataObjects.
    • Indicate whether a DataObject in the list of changed DataObjects has been created, deleted or modified.
    • Get a DataObject’s container DataObject at the point when logging began.
    • Get a DataObject’s containment property at the point when logging began.
    • Get a DataObject’s Sequence at the point when logging began.
    • Get a specific old value.
    • Get a list of old values.

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:

    • Types are allowed to contain at most one property with type ChangeSummaryType.
    • A property with type ChangeSummaryType must have many=false and readOnly=true.
    • The scope of ChangeSummaries may never overlap. If a DataObject has a property of type ChangeSummary, it cannot be directly or indirectly contained or otherwised referenced by any other DataObjects that have a property of type ChangeSummay.
    • When the DataObject containing the ChangeSummary is created, logging is by default off. Before any changes will be logged, ChangeSummary.beginLogging() must be called.
    • The ChangeSummary will not contain the creation or deletion of its containing DataObject.
    • The ChangeSummaryType MAY NOT be used to define OpenContent 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.      Implementations MAY ignore orphanHolder properties on DataObjects that themselves are orphans.  

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:

  1. Changes have been logged (getChangedDataObjects().size() > 0).
  2. No changes have been logged but isLogging() is true at the time of serialization. In this case, an empty <changeSummary/> or <changeSummary logging="true"/> element must be produced.

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
Picture (Metafile)

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]