Friday, January 30, 2009

A Universal XML Software Pattern, Part IV

There already exists a framework for inserting XML in programming languages such as Java and C++. It is known as DOM (Document Object Model). DOM and its variations, however, work at a very low level that assists reading of the document into our program but which proves insufficient to convert the XML data into objects that are meaningful to our applications. Each component of the XML document is parsed by DOM and turned into an object of the type “Element.” Since the Element class has no relationship to the application programs that are being developed, it offers no effective “methods” or activities that would help our programs process information. To fully utilize XML, DOM Element objects must be converted into a Composite pattern made up of objects that are both an integral part of our program and a functional component of a universal tree data structure.

The DOM model is not really a true reflection of the XML document. The XML document is made up of objects, arranged in a hierarchy, that belong to different classes or categories with different meanings based upon the object’s membership in those classes or categories. XML may actually format each of these objects into syntactical units called elements, reflecting the DOM model, but the different elements of XML actually have separate classes with class behaviors and meanings based upon the element’s tag name. Syntactically, the DOM programming model may be a reflection of the XML document, but semantically, representing the true meaning of the data, the Element objects of DOM are empty and need the object-oriented classes of our application programs to give them life. The DOM model works for all XML because it does not involve itself in the meaning of the data, only the syntax. Our Composite framework, on the other hand, must allow for the giving of meaning to the information.

The actual building phase of our Composite pattern involves converting a tree of primitive Element objects into a tree of objects that are meaningful citizens of our application programs.
This, in a nutshell, is our challenge: how do we best design a framework that allows our objects in the Composite tree to have the meaning that our programs need to solve particular problems while still requiring them all to have the common interface that is necessary to organize them into a Composite tree? We need to design a way to allow classes of objects to be organized into a Composite tree without requiring each of these perhaps thousands of classes of objects to have the Composite pattern interface.

To support the Composite tree, each object in the hierarchy needs to have the interface designed in the previous post here, but, to give our Composite tree a universal application, we need to be able to have it used with objects that know nothing about the hierarchy they are being assembled into and which therefore do not support the Composite pattern’s interface. As a review, this interface, which we will hereafter refer to as the TreeNode interface, has the following methods.
  • getParentNode
  • getChildrenNodes
To resolve the conflict between universality and the very specific requirements of the Composite tree we again resort to the standard patterns that exist in the world of object-oriented programmers. Specifically, the Adapter pattern, with some modification, will be used to wrap Composite-naïve objects into “wrapper” objects that support the TreeNode interface. In the following post, this design pattern will be further elaborated upon as we continue to design a universal Composite framework that can be used with any XML document.