Record Changes in Processing XML Data
You can take advantage of the ChangeSummary mechanism defined in SDO to track modifications and keep a record of changes together with the purchase order. To fulfill the second purpose, you obviously need to modify the XML schema file po_original.xsd
. (Listing 3
highlights all the necessary additions.) The imported schema sdo.xsd
(specified in SDO 2.1.0) defines ChangeSummaryType, among others. You add an element of this ChangeSummaryType in the PurchaseOrderType. You can name the element anything, but this example uses the name "changes."
To apply this new schema, you need to load it in the definePOTypes() method of Util.java. You will persist the corresponding XML file generated by CreatePO.java as po.xml. Compared with po_original.xml, po.xml has a new sub-element of <po:purchaseOrder>: <changes logging="false" />. The ProcessPO.java class (see Listing 4) processes the purchase order. When run, the program persists the processed purchase order and produces a record of changes in po_processed.xml (see Listing 5).
Listing 5 shows the changes persisted in the XML file, but the more interesting part is the <changes> element, which is now much more complex. This element captures all the changes made to the purchase order in the program. (The actual contents of the <changes> element are specified by the SDO specification.) Based on the information recorded in the content and the modified data, an application will be able to reconstruct the original data if needed. (Listing 6 captures what the program prints to the console.)
Let's review the ProcessPO.java class to analyze how SDO allows you to obtain such a detailed record of changes (refer to Listing 4):
- The line under comment 1 loads po.xml into the runtime.
- The line under comment 2 creates the ChangeSummary object associated with the purchaseOrder data object.
- To track changes, the line under comment 3 turns on the logging for the ChangeSummary object.
- From there until the line under comment 4, where the logging is turned off, all changes to purchaseOrder and its child data objects are captured in the ChangeSummary object, chngSum.
- The printout is produced by the line under comment 5, which calls the printChangeSummary() method of Util.java (see Listing 7).
In this approach, you first use getChangedDataObjects() to retrieve all the changed data objects, and then handle them based on which categories they belong to, whether created, deleted, or modified. If the data object is newly created, you print the information about this object and all its properties (by calling an annotated version of printDataObject(), an example provided in the specification). You also show the data object containing it, if one exists.
If the data object is deleted, you first identify its old containing object (if it exists), and then try to print it with printDataObject(). In this case, the printout indicates that the Apache Tuscany implementation does not generate anything. However, by calling the getOldValues() method of ChangeSummary with the deleted data object, you can examine all its properties and their values. Such information about the property of a changed data object is stored in the inner class ChangeSummary.Setting, which captures whether or not the property was set before and, if set, what the old value was (if available).
If the data object is modified, you can call printDataObject() to examine all its properties and their current values. Using getOldValues() of ChangeSummary, you can obtain the ChangeSummary.Setting objects corresponding to all properties. You carry out such an examination of the property in the private method printUpdatedProperty() of Util.java (see Listing 8).
The main part of the printUpdatedProperty() method first decides whether the property is a data type or a data object. If it is a data object, the method further checks whether the property is multiple-valued (such as an item) or single-valued (such as billTo). If it is multiple-valued, the method checks if the value is created, modified, or untouched and ultimately calls printDataObject. The method calls printDataObject() directly for single-valued properties of DataObject type. If the property is a data type, the method printUpdatedProperty() calls Setting.getValue() to retrieve the old value, and uses the method get(Property prop) of DataObject to obtain its current value.
The private method printDeletedProperty() of Util.java follows roughly the same logic. The difference is that no current value exists for any property of the deleted data object.
In the system console printout, the DataObject item is considered updated even though the program does not directly modify it at all. This is a result of all the modifications on its child item's data objects.
The next section reviews the modified purchase order.