【IT168 专稿】
跟踪数据的变化在很多软件、应用程序和商业场景中是一个基本的要求。如果要严格地实现这个需求是非常困难的,这主要是因为对文件的不同变化建模,并监视这些变化一般很难做到。从另一方面讲,在所有的程序中反复地实现这种功能要比将一个单独的模块应用到不同的应用程序中更经济实用。而服务数据对象(SDO),这个由BEA和IBM定义的异构数据访问解决方案,为开发人员提供了更容易实现的机制来从系统层跟踪数据的变化。
本文给出了一个使用Apache SDO处理XML数据的例子。由于SDO现在还不是处理XML的标准的解决方案,因此,本文还讨论了SDO中的基本的操作XML数据的方法。
一、处理XML数据的三个阶段
在本文给出的处理XML的例子分为三个不同的阶段,这些阶段如下:
1. 建立
2. 处理
3. 浏览
XML数据可以通过一个文件系统在这三个阶段之间进行传输。在本例的中心场景如下:第二步需要记录XML文件在第一阶段被建立的记录,当第三步浏览XML数据时,人们总希望知道这个文件有哪些变化。如果我们使用Word的跟踪特性,我们将会立即获得这些变化的值。
许多应用程序都有这些需求,包括实现并发控制、离线应用程序的同步,商业进程管理(BPM)系统。这部分将演示SDO如何帮助我们更容易地实现这些需求。
本文提供的XML数据是一个订购数据,代码如下:
CreatePO.java类完成了建立XML的工作。代码如下:
1. 使用XSD定义类型和属性;由于我们的数据是基于XML格式的,因此,我们首先需要在运行时定义SDO类型的属性。这个功能由Util类的definePOTypes()方法完成。在definePOTypes方法内部调用了XSDHelper类。definePOTypes()方法的代码如下:package com.company.sdo.po; import commonj.sdo.DataObject; import commonj.sdo.helper.DataFactory; public class CreatePO { public static void main(String[] args) throws Exception { //1. 使用XSD定义类型和属性 Util.definePOTypes(); //2. 建立根DataObject DataObject purchaseOrder = DataFactory.INSTANCE.create(Constants.PO_NAMESPACE, "PurchaseOrderType"); //3. 设置根DataObject的数据类型属性 purchaseOrder.setString("orderDate", "1999-10-20"); //4. 建立子DataObject DataObject shipTo = purchaseOrder.createDataObject("shipTo"); //5. 设置子DataObject的数据类型属性 shipTo.set("country", "US"); shipTo.set("name", "Alice Smith"); shipTo.set("street", "123 Maple Street"); shipTo.set("city", "Mill Valley"); shipTo.set("state", "CA"); shipTo.setString("zip", "90952"); DataObject billTo = purchaseOrder.createDataObject("billTo"); billTo.set("country", "US"); billTo.set("name", "Robert Smith"); billTo.set("street", "8 Oak Avenue"); billTo.set("city", "Mill Valley"); billTo.set("state", "PA"); billTo.setString("zip", "95819"); purchaseOrder.set("comment", "Hurry, my lawn is going wild!"); DataObject items = purchaseOrder.createDataObject("items"); //6. 为子DataObject “item”建立一个子DataObject DataObject item1 = items.createDataObject("item"); item1.set("partNum", "872-AA"); item1.set("productName", "Lawnmower"); item1.setInt("quantity", 1); item1.setString("price", "148.95"); item1.set("comment", "Confirm this is electric"); DataObject item2 = items.createDataObject("item"); item2.set("partNum", "926-AA"); item2.set("productName", "Baby Monitor"); item2.setInt("quantity", 1); item2.setString("price", "39.98"); item2.setString("shipDate", "2007-11-21"); DataObject item3 = items.createDataObject("item"); item3.set("partNum", "998-AA"); item3.set("productName", "Carpet"); item3.setInt("quantity", 1); item3.setString("price", "439.98"); item3.setString("shipDate", "2007-12-01"); //7. 将XML数据保存在一个XML文件中 Util.storeXML(purchaseOrder,"purchaseOrder", Constants.PO_XML); } }
public static void definePOTypes() throws Exception { FileInputStream fis = new FileInputStream(PO_MODEL_ORIGINAL); XSDHelper.INSTANCE.define(fis, null); fis.close(); }
在下一部分将讨论如何使用SDO的动态API,我们可以编辑订购单,并且在同时跟踪他们的变化。
三、记录处理XML数据的变化
我们可以利用在SDO中定义的ChangeSummary机制来跟踪订购单的变化。为了实现我们的第二个目的,我们先来编辑一个这个XML的schema文件po_orginal.xsd。代码如下:
public static void printChangeSummary(ChangeSummary chngSum) { if (chngSum == null) { System.out.println("ChangeSummary is not in existence!"); return; } for (Iterator it = chngSum.getChangedDataObjects().iterator(); it.hasNext();) { DataObject changedObject = (DataObject) it.next(); System.out.println(); if (chngSum.isCreated(changedObject)) {//is the changed object newly created System.out.println("Created: " + changedObject); if (changedObject.getContainer()!=null){ System.out.println("\t--- to be contained in : " + changedObject.getContainer().getType().getName() + " ---"); }else{ System.out.println("\t--- created object has no container --- "); } printAnnotatedDataObject("newly created",changedObject, 2); } else if (chngSum.isDeleted(changedObject)) { System.out.println("Deleted: " + changedObject); if (chngSum.getOldContainer(changedObject) != null){ System.out.println("\t--- originally contained in : " + chngSum.getOldContainer(changedObject).getType().getName() + " ---"); }else{ System.out.println("\t--- deleted object has no container ---"); } // a potential bug in Tuscany SDO, this shows nothing in ProcessPO.java printAnnotatedDataObject("deleted",changedObject, 2); // drill down to deleted property System.out.println("\t--- deleted property information --- "); // a potential bug in Tuscany SDO, this section shows nothing in ReviewPO.java for (Iterator settingIt = chngSum.getOldValues(changedObject).iterator(); settingIt.hasNext();) { printDeletedProperty((ChangeSummary.Setting) settingIt.next()); } System.out.println("\t--- deleted property information --- "); } else if (chngSum.isModified(changedObject)) { System.out.println("Updated: " + changedObject); // print out the updated object printAnnotatedDataObject("after update", changedObject, 2); // drill down to changed property System.out.println("\t--- property update information --- "); for (Iterator settingIt = chngSum.getOldValues(changedObject).iterator(); settingIt.hasNext();) { ChangeSummary.Setting changeSetting = (ChangeSummary.Setting) settingIt.next(); printUpdatedProperty(changeSetting, changedObject,chngSum); } System.out.println("\t--- property update information --- "); } else System.out.println("Should never come here!"); } }
package com.company.sdo.po; import java.io.FileInputStream; import java.util.List; import commonj.sdo.ChangeSummary; import commonj.sdo.DataObject; import commonj.sdo.helper.XMLDocument; import commonj.sdo.helper.XMLHelper; public class ReviewPO { public static void main(String[] args) throws Exception { Util.definePOTypes(); FileInputStream fis = new FileInputStream(Constants.PO_PROCESSED_XML); //1. 装载要处理的订购单 XMLDocument xmlDoc = XMLHelper.INSTANCE.load(fis); DataObject purchaseOrder = xmlDoc.getRootObject(); //2. 显示被编辑的订购单的信息 System.out.println(); System.out.println("---received purchase order information---"); System.out.println("Order date: " + purchaseOrder.get("orderDate")); System.out.println("Order comment: " + purchaseOrder.get("comment")); DataObject shipTo = purchaseOrder.getDataObject("shipTo"); System.out.println("Ship to name: "); Util.printDataObject(shipTo,1); DataObject billTo = purchaseOrder.getDataObject("billTo"); System.out.println("Bill to name: "); Util.printDataObject(billTo,1); DataObject items = purchaseOrder.getDataObject("items"); List itemList = items.getList("item"); System.out.println("Ordered items: "); for (int i = 0; i < itemList.size(); i++) { DataObject item = (DataObject) itemList.get(i); System.out.println("\tItem " + (i+1) + " :" ); Util.printDataObject(item,2); } //3. 显示了第二阶段的数据变化 System.out.println(); System.out.println("---review changes in purchase order ---"); ChangeSummary chngSum = purchaseOrder.getChangeSummary(); Util.printChangeSummary(chngSum); //4. 取消第二阶段的所有变化 System.out.println(); System.out.println("---action taken after reviewing the changes---"); System.out.println("\t###undo all changes###"); chngSum.undoChanges(); //5. 编辑订购单的原始版本 System.out.println(); System.out.println("---changes made in purchase order review---"); chngSum.beginLogging(); billTo.set("name", "Alice Smith"); chngSum.endLogging(); //6. 将新的变化输出到系统控制台 Util.printChangeSummary(chngSum); //7. 将改变记录保存到一个XML文件中 Util.storeXML(purchaseOrder,"purchaseOrder", Constants.PO_REVIEWED_XML); } }