Provides BusinessDocuments and Workspaces to hold them. The BusinessDocumentWorkspace allows a client to request documents from Tamino and maintains references to these documents. Within the workspace, references have unique names for clients to access the documents. A BusinessDocument represents the XML document to work on. It is mostly a JDOM tree with functionality for state handling, transfering documents to and from Tamino, XPath support, and modifying documents. XPath is a language defined by W3C to address nodes in XML documents. /Property/Address/Street e.g addresses the street element in the address of a property. X-Application (or more precisely: the various select or getDescendant methods of the BusinessDocument class) provide a subset of W3C's XPath.

Threading: The classes and methods of the Business Module are not synchronized. If you use them within multi-threading environments, you have ensure synchronization.

Modifying documents: Documents can be modified with schema-less operations or schema-based operations. Schema-less operations modify documents via JDOM, whereas schema-based operations modify documents via X-Application's BusinessNodes. The schema-less approach is easier to learn, especially if knowledge about JDOM available. The schema-based approach provides powerfull methods but is more difficult to learn.

Document States: Web applications separate presentation and control: presentation is performed on the client side by the web browser, control is performed on server side. When using the back button the user may change the current presentation whereby it does not correspond to the presentation the control expects. In that way, the user can initiate actions that are not allowed in the current state of the control. To simplify the control logic, a business document maintains its state and defines transitions to change the current state. Methods as getting and setting values of BusinessNodes depend on the state. The following diagram shows the states and the transitions.

Caution: modifying documents via JDOM does not check the state of a document. In this case, applications are responsible to ensure the appropiate state.

Dependencies

The business document package depends on the store package and the common package. Requests for creating, reading, updating or deleting XML documents are passed to the store package.

Design issues

State Pattern

To implement the state graph, the state pattern as described in [GHe94] is used. The state object is the class BusinessDocument, the abstract state class is the class BusinessDocumentState, implementations of this state class are the classes Created, Read, Modifiable, Deleted, Dead in the subpackage state. The state transitions are implemented by the methods read, modify, delete, commit, abandon. The rules for their coding are:

  1. All of the transition methods are implemented within the abstract state class by throwing an exception.
  2. Allowed transitions are overridden within the state class the transition starts. Changing to a new state is coded at the end of the method by invoking the constructor of the new state class.
  3. For changing the document object, special methods of the class BusinessDocument are used (e.g. updateDocument, rereadDocument, deleteDocument)
  4. Code of a transition that is shared for all methods when entering a certain state is implemented within the constructor of the state class.
An overview of the state implementation gives the following UML class diagram.

Implementation note

The above state graph is fully accuarate for operantions on individual document. However, there is an additional state QUASI_COMMITTED which is used when operating on multiple documents. QUASI_COMMITTED is entered by sending a QUASI_COMMIT event to either CREATED, MODIFYABLE or DEAD. This is used internally (i.e. not visibile to the user of the API) to implement BusinessDocumentWorkspace.commitAll. See also the following diagrams which show the relation of the state class to its parent class and the state transitions.

commitAll has to commit an arbitrary number of documents to the underlying database in an atomic operation. Atomic means if one commit fails (e.g. due to a database), none of the document states may be changed. This is implemented by sending a QUASI_COMMIT event to all documents, one event/document at a time. All this is wrappend by a transaction. In response to a QUASI_COMMIT event, the respective document is written to the database and - if successfull - the document state is changed to QUASI_COMMITTED. If all documents are quasi-committed successfully, the transaction is committed and the document states are changed to the respective state (READ or DEAD). If something goes wrong, the transaction is aborted and all documents in state QUASI_COMMITTED are reverted to their initial state (CREATE, MODIFY or DEAD).

Exception handling

This package uses exceptions according to the rules outlines in the common package: XExceptions are thrown to indicate problems like unavailable database and XRuntimeExceptions are thrown to report internal error. However, the following exceptions have not been updated to follow this scheme: BusinessDocumentStateException, InvalidCursorException, InvalidRecursionException, InvalidSchemaException are currently derived from XRuntimeException but should derive from XException.

Querying

To create a set of documents, the Business Document Workspace delegates a query request to its store object. The invocation of the query method of the store object requires a XQuery or a XQL statement (XPath like expression) which specifies the query.

Business Nodes

BusinessNodes maintain additional information for a document. This information is derived from the schema of the document and required to access unnamed structures which occurences in nested sequences or choices. Based on this information, X-Application provices schema-based operations which guarantees that documents are valid according to the underlying schema. E.g. required elements are created automatically even if their content may be a default content (e.g. an empty string). Similar to JDOM nodes, BusinessNodes form a tree. Some of these nodes have a reference to the underlying JDOM node. This reference is necessary for implementing operations like INSERT or REMOVE which affect the JDOM tree.

After creating a document or reading it from Tamino, the BusinessDocument holds the JDOM tree only. This is shown in the figure below. BusinessNodes are created only if a schema-based operations have to be performed, and they are discarded, if these operations have finished.

Implementation of the BusinessNode

BusinessNode is an interfaces with various implementations: ElementNode, SequenceNode, ChoiceNode, OccurrenceNode and AttributeNode. The implementation actually used for a given node is chosen according the XML schema fragments underlying this node. All of these classes inherit from the abstract base class BusinessNodeImpl. The following figure shows the relationship between these classes. The list of methods per class is only an extract to show which classes are responsible for which functionality (e.g. only an OccurrenceNode allows to insert or remove child nodes).

BusinessNode: When accessing sub-structures of a document you receive objects of type BusinessNode. You can use these objects to perform schema-based operations, e.g. inserting into an occurrence or choosing the alternative in a choice.
ElementNode: Represents an element of the schema. It may be a simple node (i.e. the type of the element defined in the underlying schema is a simple type) which allows you to set and get values. It may also be a complex node (i.e. the type of the element defined in the underlying schema is a complexType). Comples nodes have with child nodes.
SequenceNode: Is always used when the schema contains a declaration of the type sequence, which may occur within complex type declarations of elements or recursively within sequence or choice declarations. The child nodes of a SequenceNode correspond to the elements of its declaration.
ChoiceNode: Is always used when the schema contains a declaration of the type choice, which may occur within complex type declarations of elements or recursively within sequence or choice declarations. A ChoiceNode has one child node which is one of the alternatives, the declaration of the choice allows.
OccurrenceNode: Is always used for representing a list or vector or an optional of another BusinessNode (e.g. ElementNode, SequenceNode, ChoiceNode). The number of the child nodes depends on the current document instance. But all of its children have the same type.
AttributeNode: Represents an attribute of an element node. AttributeNode nodes do not have children.

Inserting BusinessNodes.

The insert operation for BusinessNode adds a tree of nodes at the desired location. The tree contains all nodes required according to the schema of the document. Inserting new nodes is only processed by OccurrenceNodes. When receiving an insert call, the class BusinessElementFactory is used to get a valid default JDOM sub-tree (see Figure: 'Sequence Diagram for insert ...'). The setChoice method in the ChoiceNode class also create a default tree, but the default tree replaces the previously selected alternative. A default tree is created according to the following rules:

  1. simple type nodes contains empty strings,
  2. the number of children of an OccurrenceNode equals the minOccurs of the corresponding schema declaration for the occurrence,
  3. the ChoiceNodes contain their first alternative (unless recursive structure require a different alternative to terminate recursion).

Removing BusinessNodes

If a BusinessElement X receives a remove request (removeThis) or has to be removed from an occurrence, the JDOM node(s) which correspond(s) to X are removed from the JDOM tree and all child BuisinessNodes of X are destroyed. Destroying a BusinessNode means that the relationship to the document, to its children, and to JDOM nodes are cleared.

Customization

Inserting a new state

If you want to add additional states, here is an outline of the necessary steps:

  1. Develop a new state class within the subpackage state, which is subclass of SingleBusinessDocumentState.
  2. Define the allowed transitions from the new state by overwriting the corresponding methods of the superclass.
  3. Within these methods code the statements to change the document at the beginning of the method. If the changes of the document object cannot be realized by the existing methods of the class SingleBusinessDocumentState, add a necessary protected method to these superclass. Invoke the following state at the end of the method.
  4. Change the existing state classes to add transitions for entering the new state

Inserting a new transition

If you want to add a new transition between existing states, here is an outline of the necessary steps:

  1. Add the method corresponding to the transition to the interface BusinessDocument.
  2. Add the method to the SingleBusinessDocument and delegate the transition to the state object.
  3. Add the method to the state class SingleBusinessDocumentState and throw an exception to prevent the execution of the method.
  4. Overwrite the method within all of the state classes where the transition is allowed. Within the overwritten method, code the state transition specific modifications of the document object.

Limitation

The current implementation

References