Skip to main content

The Architecture


The data source is designed to handle both SQL and XML data sources.

The Architecture

The data source is designed to handle both SQL and XML data sources and so it has an approach that is a bit broader than most equivalents.

The key class is DataSourceNode. DataSourceNode represents a node in the DOM in the case of XML or a ResultSet in the case of SQL. Everything that occurs in the data source is in relation to a DataSourceNode. If no specific node is set, then it is the root node, or in the case of a SQL data source, a ResultSet composed of all records from all tables in the database.

An XML file always has the concept of the current node. This is not the case with a SQL database - there is no current ResultSet. A ResultSet is only generated by the query and the foreach tags. Therefore, all other tags only make sense if they use the var attribute from a query or forEach to identify the ResultSet they are to be applied to. A tag not identifying a ResultSet will throw an exception. Refer to the Template Creator’s Guide for specific information on the report tags.

The second key concept is nested forEach loops. On every call in the DataSourceNode method, a stack of DataSourceNode’s are passed in. There is one node for each nesting level of forEach loops that the method is called from (within the loop).

There is always at least one element in the stack as stack[0] is DataSourceProvider.getRootNode(). So you can always use stack[stack.length-1] as the context you are presently operating in. The stack is provided as there are select commands that are specified to operate on a level other than the innermost level.

A DataSourceNode is only created in one of two ways. First, DataSourceProvider.getRootNode() returns the root node for the data. Second, when a forEach loop is hit, DataSourceNode.iterator() is called. DataSourceIterator().next() returns the DataSourceNode for that iteration. Therefore, the only DataSourceNodes that exist are the stack of nodes for the nested forEach loops the program is presently processing.

In addition, a given node will only have a single DataSourceIterator in use at a time. A node will never have two iterators in use at the same time. If you have a stack of four nodes, each node (except the root) will have an iterator for a total of 3 iterators in use. But no single node will have more than 1 iterator.

Finally, your methods will only be called as required by the tags in a template. If you have no out tag, the getOut method will never be called. The only method that is not mapped directly to a tag is the DataSourceNode.isExistingNode() method. This can be called before any tag method is called. (Note: the if tag calls isIf(), not isExistingNode().)

Your Basic Design

You have two key questions you must decide before writing any code. First, what is a node? Generally this is easy to answer. For XML it is a DOM node. For SQL it is a ResultSet. Your entire design, your tag select attributes— everything revolves around this question.

Your second key question is how to define a value, for example, what to display for an out tag. For XML, this is the text representation of a node. For SQL, this is a field in a row in a ResultSet. This has a substantial effect on your implementation and what is allowed in your tags. For example, an XML tag can have select=”/item/name” but a SQL tag can only have select=”${name}”; it would make no sense (the way JdbcDataSource is implemented) to have select=”select name from people” as the select for an out.

This second question affects your initial implementation. If you require ${name} for the out tag, then you need to implement that mapping as part of step one. However, most of the code for this can be copied from

  • Was this article helpful?