This document explains the general architecture of the Tamino API. The following sections are provided:
This section introduces key concepts that are required for an understanding of the Tamino API architecture. The general concept follows a component and object-oriented development approach and is described here without referring to the features of a specific object-oriented programming language.
The following graphic shows the Tamino API architecture:
For the client application only the Connection, Accessor, Object Model and Response components are of interest. The Command Invocation component is only for internal use and is invisible to the client application.
The entry point to the API is the Connection component. It is needed to establish a connection to a Tamino database. Within the context of a Connection, Tamino specific services are executed and results are returned. An integral part of this component is to provide transaction support, i.e., the starting and finishing, by commit or rollback, of Tamino transactions.
The Accessor provides high-level services to invoke specific operations on the Tamino database. This comprises insert, update, delete and query operations on Tamino XML documents as well as operations to access non-XML documents or meta data (e.g. what doctypes are stored under a specific collection).
In general, a distinction is made between access to XML or non-XML
documents. The client uses an Accessor
instance that is
capable of accessing either XML or non-XML documents, but not both.
This component describes how concrete documents that are storable in
Tamino are represented. In general, XML and non-XML are treated differently.
This is reflected by different classes within the object model.
TXMLObject
is the abstraction of XML documents whereas
TNonXMLObject
is used for the abstraction of non-XML
documents.
Furthermore TXMLObject
represents a facade to
the underlying object model (DOM, JDOM, and others). This ensures a loose
coupling between the API and the concrete XML object representation. Since each
object model is represented by its own class, the client simply chooses the
desired object model by instantiating the corresponding class such as
TDOMObjectModel
.
The role of this component is to build from low level results (XML or Non-XML documents within input streams) as they are returned by Tamino, high level response objects. Once the client has invoked a certain operation on an accessor, a high level Tamino response object is returned. The information that can be found in such a response object can be categorized as follows:
Response Information
Each Tamino response document contains general context information
that is related to the previous request. This includes information such as
return values, message codes, session ids, session keys etc. Generally,
response information is always contained within a Tamino response document.
Query-related XML documents
XML documents that are returned in response to XML related queries
are nested within Tamino's response documents. In this case the corresponding
response object provides a TXMLObjectIterator
that can
be used to navigate in a type-safe manner over the resulting
TXMLObject
instances.
Query-related Non-XML documents
Non-XML documents are returned in response to non-XML related
queries. In this case the corresponding response object provides a
TNonXMLObjectIterator
that can be used to navigate in a
type-safe manner over the resulting TNonXMLObject
instances.
Each component that is part of the architecture is responsible for its own exception handling. Exceptions that can be thrown to the outside are always component specific. Therefore, the client only receives component specific exceptions during the interaction with the component.
Each component defines a base class exception that contains more
detailed component specific exceptions. The base class exception's name
consists of the component name with the suffix
Exception
. For example, the Connections component base
class exception is named TConnectionException
.
Furthermore each of these base class exceptions is derived from the most common
API exception TException
.
However, the situation is different when pre- or postconditions are
violated for operations that are invoked by the client. In the case of contract
violation, an ViolatedPrecondition
or
ViolatedPostcondition
exception is thrown by the
affected component. These exceptions are applied for any type of pre- and
postcondition violations.
Each component can only throw either component specific exceptions or the API wide defined pre- and postcondition violation exceptions. It is not possible that a component directly throws an exception that originates from another internal client component. In these situations it is more likely that an exception that might be thrown is carried piggyback so that the client can retrieve it.
This section introduces component-specific interfaces that the application developer has to be aware of for an in depth understanding of the API. The term interface here means any type of class that is part of a component's facade. According to UML this can be a concrete class, abstract class or an interface class which only defines a set of abstract operations. The interfaces a component offers can be distinguished in service oriented interfaces and exception specific interfaces. The first generally defines the services a component offers while the second defines the component’s manner in exceptional conditions.
The UML component diagram shown below depicts the most relevant service interfaces that serve as facades to their owning components.
Please note that you use different classes when you process non-XML data instead of XML data:
XML Data | Non-XML Data |
---|---|
TXMLObjectAccessor |
TNonXMLObjectAccessor |
TXMLObject |
TNonXMLObject |
TXMLObjectIterator |
TNonXMLObjectIterator |
A client always gets access to the API by acquiring a concrete
TConnection
instance from a
TConnectionFactory
. TConnection
introduces all operations that are needed to access the concrete accessor
objects, so that this is the entry point to the Accessor component. Furthermore
it provides access to the TLocalTransaction
instance
that is bound to the client's connection.
TLocalTransaction
contains all the operations to work
with Tamino in a transaction context, which means that transactions can be
started, committed or rolled back.
The high level access to Tamino is accomplished by using a concrete
TAccessor
instance. A concrete accessor class implements
the common TAccessor
interface and provides a set of
logically grouped access operations. Currently, there are the following
concrete accessor classes: TNonXMLObjectAccessor
for
access of non-XML objects, TXMLObjectAccessor
for access
of XML objects, TStreamAccessor
for the stream-based
access of XML objects, TSystemAccessor
for access to
system information, TSchemaDefinition2Accessor
for
accessing database schema information in TSD2,
TSchemaDefinition3Accessor
for accessing database schema
information in the current schema language, based on XML Schema, and
TAdministrationAccessor
for issuing Tamino
XML Server _admin
commands.
A TNonXMLObjectAccessor
uses a given
TNonXMLObject
instance as the non-XML document
representation for an insert or delete operation. TQuery
is used for the retrieval of non-XML documents stored in Tamino. In the same
way a TXMLObjectAccessor
uses a given
TXMLObject
instance for an insert, update or delete
operation. TQuery
is the representation of a Tamino
X-Query expression and is used for the XML document retrieval.
To obtain a concrete accessor, the client always has to use a
TConnection
instance that defines the database session
with Tamino. Each accessor instance is logically bound to a specific database
session. Once the client starts a transaction on the connection’s
TTransaction
instance, the transaction context also
affects all accessors that are currently running within the connection context.
As a consequence a commit or rollback takes place on all accessor specific
operations that have been invoked during the transaction context.
Documents that are storable for Tamino are either represented by the
class TXMLObject
for XML or by the class
TNonXMLObject
for non-XML. The client uses a non-XML
accessor to pass TNonXMLObject
instances back and forth
to Tamino and proceeds in the same way concerning XML accessors and
TXMLObject
instances.
The common abstraction to all Tamino documents is
TDataObject
which also serves as a base class to
TNonXMLObject
and TXMLObject
.
TNonXMLObject
basically contains the non-XML data as an
input stream. This can be provided by the client as input data for insert
operations to Tamino or as an input stream which Tamino returned as the result
of a query operation.
The abstract base class TXMLObject
represents a
facade to the concrete underlying XML object model. A factory method can be
used to instantiate a concrete TXMLObject
class that
serves as an adapter to the object model. In Java,
TXMLObject
supports the instantiation of instances that
use DOM or JDOM as object model. Other object models can be dynamically plugged
in when the client provides implementations for
TXMLObjectModel
. The purpose behind
TXMLObjectModel
is to provide meta-information that
defines the concrete object model so that the API is able to work with it on
demand.
Tamino responds to a command invocation such as _xquery
,
_xql
, _process
, _delete
, etc. with an
XML response document. It contains general response information as well as the
result set, which consists of the documents returned from Tamino. You can
access this response information by an instance of
TResponse
. It always contains information on the
execution result such as the response code.
When the client invokes a query operation for XML documents, the
TResponse
instance provides a
TXMLObjectIterator
that can be used to navigate in a
type-safe manner over the result set of TXMLObject
instances. However, if the client only wants to obtain the first document,
getFirstXMLObject
on the
TResponse
instance is invoked to avoid the additional
indirection with the iterator.
The situation changes when the client wants to access non-XML
documents. In this case Tamino does not always respond with XML result
documents. When non-XML documents are retrieved, Tamino directly returns the
non-XML documents rather than responding with XML response documents. The API
however hides this mechanism and behaves for non-XML in much the same way as
with XML access. As a consequence, the client works with non-XML documents in
the same way as when accessing XML documents. The non-XML classes are used to
access Taminos non-XML documents. When the client invokes a query operation for
non-XML documents with the TNonXMLObjectAccessor
, the
TResponse
instance provides a
TNonXMLObjectIterator
that can be used to navigate in a
type-safe manner over the result set of TNonXMLObject
instances. If the client only wants to obtain a single non-XML document, the
getFirstNonXMLObject
operation on the
TResponse
instance can be used.
The API hides the fact that Tamino handles non-XML objects in a different way than XML objects.
As already mentioned, a clear distinction is made between the handling and access of XML and non-XML documents.
An abstraction of Tamino query expressions formulated in X-Query is the
class TQuery
which is a single class needed to retrieve
both XML documents and non-XML documents when using the SoftwareAG proprietary
query language X-Query based on
XPath.
For X-Query's successor XQuery there is the class
TXQuery
available to retrieve XML documents when using
the query language
XQuery propagated by the
W3C. Retrieval of
non-XML documents using XQuery is currently not implemented.
The Tamino API for Java provides several different ways to access and store documents in Tamino and different ways to process the response returned by Tamino. Different accessors offer access to Tamino on different abstraction levels.
The lowest level of access to Tamino is available through the
TStreamAccessor
. It treats all documents as streams of
bytes or characters. It delivers the entire response document returned by
Tamino as a single stream. The TStreamAccessor
does not
process or interpret the Tamino response document. The interpretation of the
response document is up to the client program.
On a higher abstraction level, the Tamino API offers the interfaces
TXMLObjectAccessor
and
TNonXMLObjectAccessor
. These interfaces treat each
document as a separate object represented by the
TXMLObject
and TNonXMLObject
interfaces.These accessors process and interpret the response documents
returned by Tamino and separate the result information (return value, message,
cursor information etc.) from the result content. These accessors are capable
of supporting different object models. An object model defines, how XML
documents contained in Tamino responses are delivered to the client program and
how the client program delivers documents to Tamino (DOM, JDOM, SAX,
stream).
Note the differences between a TStreamAccessor
and the stream object model. The stream object model offers stream access to
XML documents contained in the result content, while the
TStreamAccessor
offers stream access to the whole Tamino
response, without further interpretation of the response document. The stream
object model works with TXMLObject
instances, whereas
TStreamAccessor
works with
TInputStream
instances.
Note:
The TStreamAccessor
delivers the
Tamino XML Server response as a stream without any
XML parsing, thus being considerably faster than all other object model based
accessors. Notably, the largest part of processing time when using the Tamino
API for Java is spent for parsing of XML documents. This should be taken into
consideration when optimizing performance.
Apart from the previously mentioned accessors there are specialized
accessors available which provide access to specific types of information. The
TSchemaDefinition2Accessor
and the
TSchemaDefinition3Accessor
provide methods to access and
store schema information. The TSystemAccessor
and the
TAdministrationAccessor
provide access to system
information.
The result of a Tamino response is contained within the
xql:result
node of the Tamino response document. It can be a list
of XML documents or a list of literals (strings, numbers etc.). The API offers
access to a list of XML documents via the document iterators
(TXMLObjectIterator
and
TNonXMLObjectIterator
), which can be obtained from the
TResponse
class. However, there are convenience methods
in the TResponse
object to directly access the first
document of such a list.
You can directly access literals in the result content with the
TResponse
method
getQueryContentAsString()
. Currently, the Tamino
response does not contain any type information for literals, so they are always
returned as strings and the client program has to convert them.