Complete Method

The process that builds a new Design Pattern Toolkit pattern begins with an instance, called the "exemplar", of the class of applications for which the pattern is to be created and results in

The first phase of the pattern creation process identifies some of the pattern's metamodel types and identifies the purpose of each application source artifact (Java file, HTML, XML file, etc.) in the overall application design. The pattern's metamodel describes the objects that, in turn, drive the creation of application source files. For example, the designs of most web-based application classes (J2EE, portals, etc.) are expressed in terms of states, transitions and transient data objects. The specific states, transitions and data objects for an application determine how many servlets, portlets, EJB's, JSP's, HTML files, etc are to be written and so the metamodels for these classes of applications describe staes, transitions and data objects. Meanwhile, the source files for a set of database beans are driven by the schema, tables and columns of the data to be accessed, so the metamodel for a collection of database beans would describe schemas, tables and columns along with the information necessary to completely develop the database beans. The metamodel for yet another class of applications, Eclipse new resource wizards, would describe Eclipse integration information (category, wizard name, perspective, etc.) along with information such as wizard page names and the name and widget type of each field on a page.

These object types (e.g. states, transitions) are the metamodel types for the pattern. Specific applications have an instance of the metamodel which holds specific instances of those types. For example, the model for a specific web application would have specific states and specific transitions between those states. The model for a specific set of database beans would contain specific schemas, tables and columns. Note that metamodel types are not artifacts nor are they application specific data types. Rather, they are the types of objects that determine how many of the various source artifacts there will be in an application.

Begin by listing the fully qualified name (with respect to the root of the source tree or project) of every source artifact in the exemplar. This includes program source files (Java, C, C headers, HTML, JSP, XML, property files etc.). Next to each file list the reason (in terms of a model object) that the file was created. Note that the application iteslf is a model object.The table below lists several examples:

Source Artifact Role with respect to a target Model Object
.../web.xml The deployment descriptor for the web application
.../UpdateEmployeeServlet.java Holds the processing logic for the UpdateEmployee action
.../EmployeeRow.java Holds one row of data from the Employee table. Properties are typed using SQL types
../EmployeeAccess.java Holds the JDBC access logic (including SQL calls) for all selects, updates, etc to the Employee table
OrderDetails.jsp Renders the HTML for the OrderDetails state
Login.jsp Renders the HTML for the login form for the application
constants.h Declares the constants used throughout the application

After every source artifact in the application has been given a reason for existance in terms of a role and a target model object, the initial list of metamodel types can be created. Every target model object in the artifact list should have its type in the list of types. For example, if the list of target model objects includes the OrderDetails state, the Employee table and the application itself, then the metamodel types should include State, Table and Application.

In addition, use your understanding of the application to document the dependencies between metamodel types. For example, a database beans metamodel would have database column as a type which would be dependent on the database table type which, in turn, is dependent of the application. Another way to say that would be that an application has database tables, each of which have database columns.

As a checkpoint, you should have a list of all source artifacts in the application. For each artifact, you should have the file name relative to the root of the source tree, the role played by the artifact with respect to a specific target model object and, of course, the source contents of the artifact. You should also have a dependency tree of the metamodel types discovered from the target model object. The dependency tree and the list of metamodel types is very likely incomplete and will be filled in later in this process.

Reorganize the list of artifacts to group the artifacts by role and target metamodel type. For example, you might have a collection of JSP's that each render the HTML for a state in the application and a collection of Java source files, each of which contain access logic for a different database table in the application. You should notice that artifacts within any of these groups should all have the same structure, style and design.

The next step in the pattern development process involves creating a pattern template for each of the above artifact groups. Start by creating a pattern template file of type .pat. The filename should be built from the role that artifacts in the group play and from the common target metamodel type (e.g. state.render.jsp.pat and access.java.table.pat). Copy the text contents of any of the artifacts in the group into the .pat file.

Search the contents of the pattern template file for language tokens that are specific to the application and are not therefor common across all instances of the application. Class names, bean property names and types, JDBC table and column names and URL's associated with specific servlets are all examples of application-specific language tokens.Some of these tokens might seem to be variations of other tokens, but the complete token should be captured. For example, the token OrderDetailsServlet is obviously made up of a state name ("OrderDetails" which is application-specific and a suffix ("Servlet") which would be common across applications. The entire name "OrderDetailsServlet" should be captured because it is a complete language token, whereas "OrderDetails" is not.

Each captured token in the text content of the pattern template file is an instance of an attribute of one of the metamodel types. Analize each of these tokens in the pattern template file and update the metamodel by adding attributes to the metamodel types. For example, the presence of the "OrderDetailsServlet" token will require that the metamodel type for state will have an attribute named (probably) "servlet-name". The value of the servlet-name attribute for the OrderDetails state will be "OrderDetailsServlet".

It is important to note that the analysis of specific source artifacts may uncover additional metamodel type. For example, a database application will likely have database column as a metamodel type. Since there are no source artifacts whose presence is based solely on a single database column, it is likely that database column as a metamodel type won't be discovered by looking at just the artifacts and their roles. Once analysis of the application source begins, however, there will be a number of application-specific strings and tokens that can only be attributes of database columns.

There are three types of metamodel attribute:

Metamodel attributes of all three types must be captured and a later step in the process will involve the encoding of both sets of derivation rules so that only the core metamodel attributes need to be provided as input to the pattern.

As the metamodel types and attributes are identified, the application definition for the pattern's exemplar application instance can be created. The application definition (appdef) is an XML file with root element <app> representing the application. Nested directly within the <app> element are XML elements corresponding to the objects that are directly dependent on the application. For example, if the pattern describes applications that have JDBC tables which, in turn, have columns, then the appdef would look something like:

<app>
   <schema  name="..." />
   <table  name="..." >
      <column name="..."  type="..." />
      <column name="..."  type="..." />
      </table>
   <table  name="..." >
      <column name="..."  type="..." />
      <column name="..."  type="..." />
      <column name="..."  type="..." />
      <column name="..."  type="..." />
      </table>
   <table  name="..." >
      <column name="..."  type="..." />
      <column name="..."  type="..." />
      </table>
</app>
The appdef for a web application might look something like this:
<app>
   <state    name="..."  >
      <transition name="..." nextState="..." />
      <transition name="..." nextState="..." />
      </state >
   <state    name="..."  >
      <transition name="..." nextState="..." />
      </state >
   <state    name="..."  >
      <transition name="..." nextState="..." />
      <transition name="..." nextState="..." />
      <transition name="..." nextState="..." />
      <transition name="..." nextState="..." />
      </state >
</app>
For any appdef, the names of the elements correspond to the metamodel types discovered by organizing and grouping the artifacts and the attribute names correspond to the metamodel attributes discovered by analyzing the text contents of the artifacts in each group. Specific element instances in the appdef correspond to the metamodel objects (e.g the specific states or specific tables, etc,) in the exemplar. Specific attribute values are populated with the application-specific tokens found in the exemplar's source artifacts. Once the pattern is complete, however, appdefs will be built from information gathered during an interview with a customer or end user.

Note how an application definition file contains an instance of the application's metamodel.

With this information you can build the controller component of the pattern. The controller is usually a single pattern template file named "control.pat" with additional auxillary files to be discussed later. The structure of the control.pat template is driven by the pattern's metamodel. For the pattern whose model consists of states that contain transitions, the control.pat would look something like this:

    *** Generate application level artifacts
    
    <useNode node="/app"  name="app">
    
    <start template="..."  resource="..."   />
    <start template="..."  resource="..."   />
    
    *** Iterate over the states in the application and generate 
    *** state-specific artifacts for each state

    <iterate nodes="/app/state" name="curState">

       *** Generate artifacts for the current state
       
       <start template="..."  resource="..."   />
       <start template="..."  resource="..."   />
       <start template="..."  resource="..."   />

       *** Iterate over the transitions for the current state and
       *** generate transition-specific artifacts for each transition

       <iterate nodes="curState/transition" name="curTransition">
       
          <start template="..."  resource="..."   />
       
       </iterate

    </iterate

Each start tag will apply the application definition to a single pattern template. The pattern template will have been built from the exemplar application using artifacts that played the same role for a particular metamodel type.

Once the exemplar's appdef has been filled in, the pattern templates (there is one for each group of artifacts) can be completed. Each template will be modified by embedded pattern template tags into the template's content. There are three sets of tags:

To checkpoint, the following pattern deliverables should have been built by now:

  • An application definition containing the business objects and attributes for the exemplar application
  • A metamodel describing the data objects necessary in order to build a complete application
  • You should be able to apply the pattern to the exemplar's appdef to completely regenerate the original exemplat application. Once the model, view and controller (appdef, templates and control.pat, respectively) have been debugged and stabilized, you can continue to verify the pattern by gathering requirements (as a set of the pattern's model objects) and generate other instances of this application class

    A final step in the building of the pattern reduces the size of the application definition significantly. Two new template patterns will be created (naming.pat and derived.pat) to hold a description of how to derive the two sets of derived model object attributes (Naming and Derived) from the set of Core attributes. This description uses <iterate> tags to navigate through all of the known business objects and uses <setAttr> and <newText> tags to create and set the Naming and Derived attributes. Complex patterns may also create Derived model objects with the <newNode> tag.

    Once the naming.pat and derived.pat control files have been created, they can be included with the <include> tag from within the control.pat controller. Note that the naming conventions embodied in the naming.pat controller can easily be overridden by one-off patterns that use the <override> tag and provide their own naming.pat controller.


    © Copyright IBM Corporation 2000, 2005. All Rights Reserved.