DOM4J: Adding an Object Model

A client application handles XML documents by using an accessor to pass TXMLObject instances to Tamino. TXMLObject supports DOM and JDOM as object models, but you can add other object models as well. This document explains the steps involved using DOM4J as an example.


Object Models

The underlying XML object model is represented by the abstract base class TXMLObject. Using a factory method you can instantiate a TXMLObject that serves as an adapter to the object model. DOM and JDOM are directly supported as object models, but you can dynamically plug in other object models provided that the client offers an implementation for TXMLObjectModel. TXMLObjectModel provides meta-information that defines the object model so that it can be used within the API.

Using an Object Model

In the context of the Tamino API, you use an XML object model as follows (xxx here stands for an arbitrary object model):

graphics/objectModel1.png

  1. Use a TConnectionFactory to create a TConnection instance for establishing a connection to a Tamino database

  2. Create an instance of the TxxxObjectModel.

  3. Let the TConnection create an Accessor for the TxxxObjectModel.

  4. Now you can use the Accessor to send a query to Tamino.

  5. The resulting TResponse instance is able to create the Document instance specific to that object model.

Writing an Object Model

An object model is defined by the following classes:

  • the generic class or interface of the underlying object model that represents the root node type for an XML document; for DOM4J this is the Element interface.

  • TXMLObject adapter implementation which adapts some interfaces of the underlying object model

  • an implementation for interpreting the input stream

As a consequence, the abstract base class TXMLObjectModel defines operations to access the meta class for the node type, the TXMLObject adapter and the TResponseBuilder. To use a new object model you need to provide the appropriate TXMLObjectModel implementation along with the TXMLObject adapter and the TxxxInputStreamInterpreter implementation.

graphics/objectModel2.png

  1. The TxxxObjectModel describes which xxx specific Document, Element, TxxxAdapter and TxxxInputStreamInterpreter is used by the xxx object model.

  2. To use this object model it must be registered in the TXMLObjectModel with the method: TXMLObjectModel.register(TXMLObjectModel xmlObjectModel).

  3. A TxxxElementIterator is needed to navigate unidirectional and type safe over the xxx specific Elements.

  4. TxxxInputStreamInterpreter interprets the TAMINO Stream and creates the xxx specific Document instance

  5. The TxxxAdapter adapts to the xxx specific object model to the generic TXMLObject interface.

Assembling a New Object Model

In this section we use DOM4J as an example to show which classes are needed for the implementation of a new object model. You can use the example code available with this documentation ( <Tamino installaion directory>/SDK/TaminoAPI4J/Documentation/inoapi/listings/dom4j/ ) as a template for supporting another object model in the Tamino API.

In the following sections we discuss the implementation of the classes needed based on the DOM4J object model implementation.

First, you must determine a short name for the object model, by which all classes are recognized as belonging to the adapter implementation of the same object model. Here, we use "xxx" as name to refer to the new object model adapter.

You need to create two packages, one containing the complete implementation of the object model adapter and another package with the implementation of the input stream interpreter. Using "xxx" the package names are as follows:

  • com.softwareag.tamino.db.api.objectModel.xxx

  • com.softwareag.tamino.db.api.response.xxx

TxxxAdapter

TXMLObject is the abstract super class to represent an XML object. To create the specific adapter class, this class must be extended. Example:

com.softwareag.tamino.db.api.objectModel.dom4j.TDOM4JAdapter

Start of instruction setHow to implement the TxxxAdapter

  1. Copy the class

    com.softwareag.tamino.db.api.objectModel.dom4j.TDOM4JAdapter

    to the new package:

    com.softwareag.tamino.db.api.objectModel.xxx
  2. Rename the adapter class to:

    com.softwareag.tamino.db.api.objectModel.TxxxAdapter
  3. Replace the references to org.dom4j.Element and org.dom4j.Document with references to appropriate classes of the object model "xxx".

  4. In the implementation of the object model, identify and use the methods that perform the following tasks:

    • get the related Document

    • remove an Attribute

    • get an Attribute

    • add an Attribute

    • set a value

    • get the qualified name

    • get the root element

You also need a way to read an InputStream and create your specific Document instance. In DOM4J this is SAXReader, which is used in the readFrom() methods.

The best way to make these changes is to replace the import instructions in your new Adapter class (e.g. replace dom4j specific imports by imports for your new model), and to check any compiler messages about missing methods.

TxxxInputStreamInterpreter

Start of instruction setHow to implement the TxxxInputStreamInterpreter

  1. Copy the class

    com.softwareag.tamino.db.api.response.dom4j.TDOM4JInputStreamInterpreter

    to the new package:

    com.softwareag.tamino.db.api.response.xxx
  2. Rename the class to:

       com.softwareag.tamino.db.api.response.TxxxInputStreamInterpreter
  3. In the import instructions replace the following classes

       org.dom4j.Document;
       org.dom4j.Element;
       org.dom4j.Namespace;
       org.dom4j.QName;
       org.dom4j.DocumentException;
       org.dom4j.io.SAXReader;
    

    with the corresponding classes of the new object model.

  4. In the implementation of the new object model, identify these classes and methods of DOM4J and change it appropriately for TxxxInputStreamInterpreter:

    Class Method
    org.dom4j.Document getRootElement()
    org.dom4j.Element element()
    elements()
    attributeValue()
    getText()
    org.dom4j.Namespace get()
    org.dom4j.QName  
    org.dom4j.DocumentException  
    org.dom4j.io.SAXReader read()

ObjectModel

TXMLObjectModel contains operations needed to define and control an XML object model. Each XML object model is defined by four class instances:

Element

An Element class represents either an element or a fragment of the document tree.

Document

A Document class represents the complete document.

Adapter

An Adapter class adapts the physical object model to TXMLObject.

InputStreamAdapter

An InputStreamInterpreter class determines for a physical object model the way to handle response documents returned by Tamino.

Start of instruction setHow to implement the TxxxObjectModel

  1. Copy the class

    com.softwareag.tamino.db.api.objectModel.dom4j.TDOM4JObjectModel

    to the new package:

    com.softwareag.tamino.db.api.objectModel.xxx.TxxxObjectModel
  2. Change the constructor

       protected TxxxObjectModel() {
           super( "xxx" ,
                  xxx.Document.class ,
                  xxx.Element.class ,
                  com.softwareag.tamino.db.api.objectModel.xxx.TxxxAdapter.class ,
                  com.softwareag.tamino.db.api.response.xxx.TxxxInputStreamInterpreter.class );
           }
    

    You must use your specific Document, Element, Adapter and InputStreamInterpreter classes.

  3. Change occurrences of TDOM4JObjectModel to TxxxObjectModel.

Outputter

If your object model does not provide a class to serialize XML into a string, you have to write your own class.

Start of instruction setHow to implement an outputter class:

  1. Copy the classes

    com.softwareag.tamino.db.api.objectModel.dom4j.TDOM4JXMLOutputter
    com.softwareag.tamino.db.api.objectModel.dom4j.TDOM4JNamespaceStack

    into the package

    com.softwareag.tamino.db.api.objectModel.xxx
  2. Rename these classes as:

    com.softwareag.tamino.db.api.objectModel.xxx.TxxxXMLOutputter
    com.softwareag.tamino.db.api.objectModel.xxx.TxxxNamespaceStack
  3. You must replace the following classes and methods:

    Class Method / Constant
    org.dom4j.Attribute getNamespace()
    getQualifiedName()
    getValue()
    org.dom4j.CDATA asXML()
    org.dom4j.Comment asXML()
    org.dom4j.DocumentType getPublicID()
    getSystemID()
    getElementName()
    org.dom4j.Document getRootElement()
    org.dom4j.Element getDocument()
    getNamespacePrefix()
    getParent()
    elements()
    getQualifiedName()
    getNamespace()
    additionalNamespace()
    attributes()
    getTextTrim()
    getText()
    org.dom4j.Entity asXML()
    org.dom4j.Namespace get()
    XML_NAMESPACE()
    NO_NAMESPACE()
    getUri()
    getPrefix()
    org.dom4j.ProcessingInstruction  
  4. In the implementation of TxxxXMLOutputter replace occurrences of TDOM4JNamespaceStack with TxxxNamespaceStack.

Putting Together

At this point, you have a complete implementation of all necessary classes. Compile these classes, include them and those of the original object model in the class path. You can then use the new object model in your client applications.

Using the DOM4J Object Model: A Sample

To use the implementation for the DOM4J object model you need the DOM4J implementation which you can download at http://www.dom4j.org/. You need to include the DOM4J classes and the adapter classes in your classpath. You will find the adapter classes in the file JavaTaminoAPIExamples.jar in the directory <TaminoAPIDir>/examples.

In the sample below you can see how to register the new object model so that the Tamino API knows about it. In the last line, an accessor is instantiated that uses the new object model.

   // Constant for the database URI. Please edit to use your URI of interest.
   private final static String DATABASE_URI = "http://localhost/tamino/mydb";

   // Obtain the connection factory
   TConnectionFactory connectionFactory = TConnectionFactory.getInstance();

   // Obtain the connection to the database
   TConnection connection = connectionFactory.newConnection( databaseURI );

   // Instantiate the specific TxxxObjectModel
   TxxxObjectModel xxxObjectModel = TxxxObjectModel.getInstance();

   // Register the object model
   TXMLObjectModel.register( xxxObjectModel );

   // Obtain the concrete TxxxObjectAccessor with an underlying xxx object model
   TXMLAccessor accessor = connection.newXMLObjectAccessor( TAccessLocation.newInstance( "ino:etc" , xxxObjectModel );