Login | Register
My pages Projects Community openCollabNet

StringTemplate Evaluation

Overview

StringTemplate is a library to be used in java programs in order to fill data into template strings. The java code is responsable for reading the template, associating a value to each attribute and writting the result to a stream.

The language does not allow side-effect meaning that the value of the attributes can't be changed in the template and the order of the statements does not influence the result.

Reflection is used to extract information from objects either by calling getter methods or directly accesing public fields. The value of the attributes in the template is the result of calling toString() on the referred object.

Developement model

  1. Create a StringTemplate object by passing a string to the constructor or reading it from a file (suppose the object is stp)
  2. Associate objects to template-attributes using:
      stp.setAttribute("packages", Model.getFactory().getAllPackages());
      stp.setAttribute("packages_byname", ...);
  3. From within the template you can access public fields by using:
      stp.fieldName
      
  4. or you can call isSomething or getSomething methods on the objects that are binded to the attributes (parameters can't be passed):
      $packages.size$ will send the message getSize() to the object bind to packages
      $packages.empty$ will send the message isEmpty() to the object bind to packages
      
  5. stp.toString() will return the result of filling in the attributes

Conditionals

The conditional operator:

$if(expr)$
$else$
$endif$
evaluates expr and if the value evaluates to Boolean true or to an non-empty string than the if-block is evaluated otherwise the else-block is evaluated. No parameters can be passed to the method hance requiring individual methods implemented for each test (e.g. isClassInPackageUtils(), isClassInPackageUI etc.)

Iteration

Iteration is implemented with a syntax similar to Smalltalk:

 actors:{actor|$actor.Name$}

Sorting

Sorting has to be done in the model (e.g. getListSortedByName, getListSortedByAddress).

Multiple data sources

The program that uses the StringTemplate library is responsible for combining multiple data sources and providing the template author the name of the attributes to use. If two data sources are used to use each one independenly on model for each must be provided. When cobining the two sources a new model must be provided in addition to the two.

Tools

The template engine is licensed under the BSD License and no StringTemplate-capable editor could be found.

Code

  • Shows a subset of classes based on the name of the containing package in chapter 1.
  • For each of these classes, shows all the names and types of the attributes. For those classes that doesn't have attributes include instead the text "No attributes."
    	  <h1>Chapter 1<h1>
    
    	  $packages:{package| 
    	   <h2>$package.name$</h2>
    	   <ul> $package.classes:{class|
    	    <li>$class.name$
                 <ul>
    	      <li>
    	       $if(class.attributes)$ <! test if getAttributes returns null !>
    	         $class.attributes:{attr| $attr.name$ $attr.type$}$
    	       $else$
    	         No Attributes
    	       $endif$}$
    	      </li>
                 </ul>
    	    </li>
    	  </ul>
    	  
  • Shows a subset of classes based on the name of one of the stereotypes in chapter 2.
  • For each of these classes, shows the signature of all the operations including return value, direction, name, and type of each parameter. Each method as a bullet in a bulleted list.

    Note:Another solution is similar to the above but supposes that a stereotype know all classes that use it.

    	   $stereotypes:{stereotype|
    	    $classes:{class|
    	     $if(class.(stereotype$stereotype.name$))$ <! calls class.isStereotype<name>() !>
    	      $class.name$
    	      <ul>
    	      $class.methods:{method|
    	        <ul>
    		 <li>Name: $method.name$</li>
    		 <li>Returns: $method.returnType$</li>
    		 <li>Visiblility: $method.visibility$</li>
    		 <ul>
    		 $method.parameters:{paramenter|
    		  <li>$parameter.name$: $parameter.type$</li>
    		 }$
    		 </ul>
    		</ul>
    	      }$
    	      </ul>
    	     $else$ <! do nothing !>
    	     $endif$
    	    }$
    	   }$
    	  

  • Show a subset of classes based on the existance of a parameter named "something" in any of the operations in the class in chapter 3.
  • For each of these classes, if they contain operations other than the one named "something", show these in a table with one operation on each line with the operation name in the first column and then one column per distinct type for all parameters with the names of the parameters filled in the table. For those classes that doesn't have any other operations, include instead the text "No other operations."

    Not possible. No parameters can be pushed to the model so the only solution would be for each method to have is<Something>Available(). Calling the methods would not be a problem $method.($something$Available)$ but is unlikely that these methods will be available. With a message passing mechanism like in Smalltalk this would not be a problem but in java the object can't intercept the message that it does not define.

  • Show all use case diagrams in chapter 4
  • Under each use case diagram, a list of actors and a list of use cases both with their explanations.
    	  <h1>Chapter 4<h1>
    
    	  <! naming convention assumed and the model takes care of creating the images !>
    	  $usecase_diagrams:{diagram|
    	    <img src="$diagram.name$.png" alt="$diagram.name$"/>
    	    <h3>Actors</h3>
    	     <ul>
    	     $diagram.actors:{actor|
    	      <li>$actor.name$ - $actor.expanation$</li>
    	     }$	    
    	     </ul>    
    	    <h3>Usecases</h3>
    	     <ul>
    	     $diagram.usecases:{usecase|
    	      <li>$usecase.name$ - $usecase.expanation$</li>
    	     }$	    
    	     </ul>    
    	  }$
    	  
  • Show the use cases that are linked to a requirement (requirements fetched from some other tool than argouml indexed on the use case names) in chapter 5.
  • Under each use case, show the requirement text.

    Note:The Java model is responsible for combining the two sources; inside the template there is a single model

    	   $usecases:{usecase|
    	    $usecase.name$
    	    <ul>
    	    $requirements:{requirement|
    	     $if(usecase.(LinkedTo$requirement.name$))$ <!calls usecase.isLinkedTo<name>()!>
    	      <li>$requirement.text$</li>
    	     $else$ <! do nothing !>
    	     $endif$
    	    }$
    	    </ul>
    	   }$
          

  • Create a template that creates a html site with two frames. One tree on the left with all actors, use cases, classes, attributes, operations, and then one page per actor, class, use case.

    Note:The code combinining the two frames is static. The tree frame is generated using a single template, the detailed frames are generated by applying templates specific for actor/usecase/class etc. Calling the template and writing the file for each item must be done in code.

          

Notes

  • Length - easy to learn by non-programmers provided all required java code in the model is available
  • Complexity - high - java code must be build in order to perform simple tests because no parameters can be passed to the calls in the model
  • Error prone - if the java code is not build correctly side-effect can be introduced in the code; using $ as a delimiter is confusing as you can't easily tell if it an opening or closing delimiter. < and > delimiters can't be used in SGML type output
  • Error spoting - if the template is complex error spotting could be hard without a proper tool