Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

IBM WebSphere Developer Technical Journal: Get started with model-driven development using the Design Pattern Toolkit -- Part 2

Accessing the DPTK data model

Chris Gerken (cgerken@us.ibm.com), Senior Software Engineer, IBM
Chris Gerken is a member of the Asset Reuse Enablement Team within the IBM Software Services for WebSphere group. He created and wrote the Design Pattern Toolkit.
Roland Barcia, Certified IT Specialist, IBM
Roland Barcia is a Certified IT Specialist for IBM Software Services for WebSphere in the New York/New Jersey Metro area. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration. For more information on Roland, visit his Web site.

Summary:  This series exposes the practicality and benefits of model-driven development using the Design Pattern Toolkit (DPTK) to create pattern templates that capture your best practices. Accessing your model data is the key to writing good templates, and so this installment describes the query language and the special model and data access tags provided by the DPTK that give you direct access to the information you need to create effective and efficient templates.

Date:  25 Oct 2006
Level:  Intermediate
Also available in:   Chinese  Japanese

Activity:  4012 views
Comments:  

From the IBM WebSphere Developer Technical Journal.

Introduction

The Design Pattern Toolkit (DPTK) is an Eclipse-enabled template engine for generating applications based on customizable, model-driven architecture transformations. We introduced the basics of the code generation facility in the DPTK in a previous article. In this article, we will discuss details on how you can access the model data from your templates.

Authoring Design Pattern Toolkit (DPTK) patterns requires familiarity with two subject areas: how to access the data model and how to use the available DPTK tags. We will focus here on the first topic, discussing the DPTK query language (which is very similar to abbreviated XPath), along with several simple tags that read the model and write the data directly to the template output.

Visit IBM alphaWorks to learn more about or to download the Design Pattern Toolkit.


The model and the data access tags

The data model in DPTK is presented to the DPTK templates as a document object model (DOM). The data usually comes from an XML file or XML string, but it can come from other sources as well, such as Java™ source files or flat files. Even DPTK templates have been used as a source for the model in patterns, such as the one that migrates DPTK patterns to JET patterns.

Although the data model can originate from any of many possible sources, it is always accessed as a DOM, and that DOM is always accessed using DPTK tags that accept query expressions as one or more attributes.

There are three simple DPTK tags that read from the model and write that information to the template's output. Each tag has a node attribute that takes a query expression describing a single model node in the DOM. Once the node is found, the tag performs its specific action against that node.

Each of the three tags writes a different aspect of the specified model node:

  • <content> - writes the content (the text between the start and end tag in an XML file) for the one node described by its node attribute.
  • <attr> - writes the value of one of the attributes for the specified node.
  • <dump> - writes an XML representation of the DOM subtree under the specified node.

Template authoring becomes straightforward with these tags, if not a bit tedious. As you determine which sections of the generated artifact content is dynamic, you build out the model of exactly what dynamic data is needed by the template. The dynamic content sections of the template are easily replaced by the appropriate <content>, <attr> or <dump> tags that use query expressions to target the correct model nodes. It is here, though, that a common question is asked: How do you write the query expression to get the correct node from an arbitrarily complex DOM?


An example

  1. Import the Data Model Pattern project from the download file included with this article, dataModelPattern.zip, using the Import From Project Interchange wizard.

  2. Open template write.pat in an editor to see an example of each of the three DPTK tags that write out model data (Figure 1).



    Figure 1. write.pat template
    Figure 1. write.pat template

    A sample input model for this pattern can be found in simple.xml:



    Figure 2. simple.xml
    Figure 2. simple.xml

  3. You can transform the sample input model with this pattern by selecting the model (file simple.xml) and using the right mouse button to select Apply Pattern from the context menu.



    Figure 3. Transform template with pattern
    Figure 3. Transform template with pattern

  4. You will be prompted to select the pattern with which to transform the model (Figure 4).



    Figure 4. Available patterns
    Figure 4. Available patterns

  5. Select Data Model Pattern and then OK. You should see an informational message box telling you that the pattern was applied successfully.

    Note that as a result of the pattern being applied, a new project named Results, containing a file named write.txt, has been created. When you open file write.txt, you will see how the DPTK tags in template write.pat, above, wrote out data that came from the input model in simple.xml.



    Figure 5. write.txt
    Figure 5. write.txt


DPTK query expressions

A DPTK query expression is a string that describes how to traverse the DOM. A traversal can end at a single node, or at several nodes, or at no nodes at all. We say that the query expression results in the set of nodes at which the navigation ends. When you pass a query expression into a tag through the node or nodes attributes, you're indicating that the tag should traverse the model, as described by the query expression, and act against the resulting nodes.

By convention, the node attribute specifies a query expression that should result in exactly one node. If the expression results in more than one node, then only the first node is used. If no nodes result, then an error is thrown. Meanwhile, the nodes attribute specifies a query expression that can result in any number (including zero) of nodes.

Syntactically, a query expression has a start node, followed by a sequence of steps that describe how to move from one node to another related node. There are two kinds of start node, differentiated by syntax:

  • To start at the document node (the parent of the high-level element in an XML input), simply begin the query expression with a forward slash ("/").
  • To start at any other node in the DOM, start the query expression with a variable name that will be associated with that node when the query expression is interpreted. Tags such as <iterate>, <useNode>, <exists> and <extend> can be used to associate variable names with specific nodes.

The query expression is processed by building a sequence of node collections:

  • The first collection contains only the start node.
  • The second collection contains all nodes that can be reached from the start node in the manner described by the first step.
  • The third collection contains all nodes that can be reached from any of the nodes in the second collection in the manner described by the second step.
  • The final collection of nodes gathered during the last step in the query expression is the set of resulting nodes for the query expression.
  • If there are no steps in the query expression, the query expression results in the start node, pending any additional filtering.

The DPTK query expression language provides for several kinds of steps with which to specify model traversals:

  • Parent step: move from a node to that node's parent:
    syntax: ..

  • Child step: move from a node to all of that node's child nodes that have a given name:
    syntax: child-node-name

  • All children step: move from a node to all of that node's children:
    syntax: *


Figure 6. Query expressions
Figure 6. Query expressions

Figure 6 shows two DPTK query expressions made up of different kinds of steps. The first, /portlet/*/link toPage='6' starts at the document (the parent of the portlet element) and has three steps:

  1. The first step, portlet, collects all nodes named "portlet" that are children of the document.

  2. The second step, "*" navigates to all child nodes of the node named "portlet".

  3. The third step, link toPage='6', navigates to all page node children that are named "link" and which have an attribute toPage whose value is '6'.

The second query expression, curlink/../.., starts at the node associated with variable curlink (the absence of a leading forward slash means the first token is a variable name) and navigates to the parents of the parents of that start node. It's up to the pattern author to ensure that the specified variable name is correctly associated with the correct node by previous DPTK tags.


Exercises

Listed below is the content of the file complex.xml in the sample pattern you loaded into Eclipse. This file stores information on the members of a swim team.


Listing 1

<swim>

   <meet host-team='02' pool="Milburne" >
      <event number="1" gender="F" distance="400" stroke="medly" relay="true" />
      <event number="2" gender="M" distance="400" stroke="medly" relay="true" />
      <event number="3" gender="F" distance="100" stroke="freestyle" relay="false" />
      <event number="4" gender="M" distance="100" stroke="freestyle" relay="false" />
      <event number="5" gender="F" distance="100" stroke="butterfly" relay="false" />
      <event number="6" gender="M" distance="100" stroke="butterfly" relay="false" />
      <event number="7" gender="F" distance="100" stroke="backstroke" relay="false" />
      <event number="8" gender="M" distance="100" stroke="backstroke" relay="false" />
      <event number="9" gender="F" distance="100" stroke="breaststroke" relay="false" />
      <event number="10" gender="M" distance="100" stroke="breaststroke" relay="false" />
      <event number="11" gender="F" distance="400" stroke="free" relay="true" />
      <event number="12" gender="M" distance="400" stroke="free" relay="true" />
	    
      <swimmer name="Fred" teamref="01">
         <entry event="2" />
         <entry event="10" />
	 <entry event="12" />
      </swimmer>
      <swimmer name="Sam" teamref="02">
         <entry event="6" />
         <entry event="8" />
      </swimmer>
      <swimmer name="Mary" teamref="01">
         <entry event="5" />
         <entry event="9" />
         <entry event="11" />
      </swimmer>

      <team id="01" name="Eastwood" />
      <team id="02" name="Westlake" />

   </meet>
</swim>

The data has been normalized so that values are stored only once, requiring the use of foreign keys in various elements. For example, to get the name of Mary's team, you have to find the <team> element whose ID value is 01. Likewise, to find her events, you need to iterate over the <entry> elements nested in her <swimmer> element, and look up the <event> element whose number attribute matches the entry's event attribute.

Pattern templates often use iteration and filtering techniques to correctly generate artifacts. We will build up an example of a template that generates a report listing all teams, all swimmers for each team, and the events in which each swimmer will swim.

We start with an iteration over all of the teams. To get the collection of elements representing teams at the meet, we must start at the document and navigate through elements <swim>, <meet> and <team>, in that order. The DPTK query expression describing that navigation is /swim/meet/team, and we use that expression in the nodes attribute of an <iterate> tag:

<iterate nodes="/swim/meet/team" name="team">

</iterate>

The <iterate> tag will collect all nodes that match the query expression. For each node in that collection, the tag will associate that node with the name "team" and will process its contents once.

For each team, we want to write out a line with the team's name followed by a listing of swimmers for that team. Remembering that the <team> element is associated with variable name "team", we can use that variable name when referring to the team's attributes:

<iterate nodes="/swim/meet/team" name="team">

Team: <attr node="team" name="name"/> </iterate>

In the <attr> tag, the query expression "team" doesn't start with a forward slash, so the first token, "team", is taken to be a variable name. Since there are no steps following the variable name, this query expression results in a single node which happens to be the current <team> node. The <attr> tag has the effect of writing out the name attribute of the current team.

Once we've written the team's name, we need to iterate over the swimmers on the team. To collect the nodes representing all of the <swimmer> elements associated with a given <team> element, we need to navigate from the document through elements <swim>, <meet>, and <swimmer>. When stepping from the <meet> element to the <swimmer> element, we only want <swimmer> elements whose teamref attribute matches the current team's ID attribute.

The query expression that performs this navigation uses three steps (the last one has a filter): /swim/meet/swimmer teamref='%team(id)%' . We nest an <iterate> tag inside the first <iterate> and indicate that within the scope of the iteration, variable name "swimmer" will be associated with the current <swimmer> element.

<iterate nodes="/swim/meet/team" name="team">

Team: <attr node="team" name="name"/> 
<iterate nodes="/swim/meet/swimmer teamref='%team(id)%'" name="swimmer">

          Swimmer: <attr node="swimmer" name="name" />
</iterate>
</iterate>

We will create a template in our data model pattern to hold the above template section:

  1. Create a new file in the project root directory and name the new file swimming.pat.



    Figure 7. Create a new file
    Figure 7. Create a new file

  2. Once you have created the new template, you need to edit the control.pat file, which controls which templates get applied to the model. Since we're using a different model than before, you don't want to apply the write.pat template, which assumes the old model. When you edit the control.pat template, you just have to change the one <start> tag:



    Figure 8. Modify start tag
    Figure 8. Modify start tag

  3. You can now apply the pattern to the model in the complex.xml file. The pattern now generates the file swimming.txt.



    Figure 9. Apply pattern to the model
    Figure 9. Apply pattern to the model

  4. The last thing the template has to do is list the events for each swimmer, but the navigation to do this is a bit more complex. Each <swimmer> element has some number of nested <entry> elements that hold the value with which to search for the correct <event> element. The navigation used by the iterate starts at the current swimmer and traverses down to all nested <entry> elements. The query expression for this is swimmer/entry.

    For each <entry> element, navigate to the correct <event> element by starting at the document node and traversing <swim>, <meet>, and <event> elements. The final step is also filtered using the <event> number attribute and the <entry> event attribute. The template now looks like this:



    Figure 10. Template with complex navigation
    Figure 10. Template with complex navigation

    And it produces an output file like this:



    Figure 11. Template output
    Figure 11. Template output

    Notice that the three <attr> tags for the event all have the same query expression. We can simplify the template considerably with a <useNode> tag inside the inner <iterate> tag to temporarily associate the correct <event> element with the variable name "event":



    Figure 12. Simplified template
    Figure 12. Simplified template

  5. Now that the <attr> tags take less space, it's easier to make the template produce a more nicely formatted output:



    Figure 13. Template output
    Figure 13. Template output


Conclusion

Understanding how to access your model data is the key to writing good templates. The Design Pattern Toolkit provides special model and data access tags that can access elements from your internal model, which is represented as a DOM. The DPTK query language further compacts your templates by enabling you direct access to almost anywhere in the DOM with a single string. This article described the DPTK expression language and demonstrated how it can be applied to create an effective way of accessing your data model.


Acknowledgements

The authors would like to thank Geoffrey Hambrick for his review of this article.



Download

DescriptionNameSizeDownload method
Code sampleDataModelArticle.zip7 KBHTTP

Information about download methods


Resources

About the authors

Chris Gerken is a member of the Asset Reuse Enablement Team within the IBM Software Services for WebSphere group. He created and wrote the Design Pattern Toolkit.

Roland Barcia is a Certified IT Specialist for IBM Software Services for WebSphere in the New York/New Jersey Metro area. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration. For more information on Roland, visit his Web site.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, SOA and Web services, Architecture
ArticleID=170016
ArticleTitle=IBM WebSphere Developer Technical Journal: Get started with model-driven development using the Design Pattern Toolkit -- Part 2
publish-date=10252006
author1-email=cgerken@us.ibm.com
author1-email-cc=
author2-email=barcia@us.ibm.com
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers