Creating RapTier Templates

download the source code

Introduction

The purpose of this article is to provide a look "under the hood" of Active Templates and show some examples that you can use as a start point for your own templates. If you are familiar with the fundamentals of ASP.NET or JSP you will be surprised how little you need to learn to start creating your own code generation templates that utilize all the power of .Net Framework and flexibility of C#.

Unlike many other template technologies that use "passive" templates with a limited set of tags replaced during generation, Active Templates is a mixture of static code and C# instructions that control the way the code is generated.

Let's take a look at the architecture and syntax of Active Templates before proceeding further.

Active Templates Architecture

Every time before RapTier generates code, Active Template Engine (ATE) checks whether any template file (the file with the atcs extension) in the selected template group was updated since the last compilation. If it finds a modified template file, ATE converts all the group templates into C# classes, which inherit the SharpPower.Ate.TextFileGenerator abstract class, and compiles them into a .NET assembly.

After the assembly is compiled, ATE loads it, creates the new instances of the necessary template classes and calls the Generate method created by the ATE from the template code.

Active Template Syntax

A template file contains any combination of the following elements:

  • Base output code (C#, VB.NET, Java, HTML, ASP.NET, SQL, etc.)
  • Code blocks
  • Named code blocks
  • Comments
Code Blocks:
Code blocks are used to define inline code or inline expressions that execute when the template is processed. Use inline code to define code blocks or control flow blocks. Use inline expressions as a shortcut for calling the Writer.Write method.

Script Block Description
<# code #> Defines one or more lines of code that executes when the template is processed.
<# code ##>

Defines one or more lines of code that executes when the template is processed. Ignores all white space characters (including the EndOfLine symbol) starting from the ending tag ##> till either the end of line or any non-white space symbol.

<#= expression #> Shortcut for <# Writer.Write(expression); #>
<#= expression ##> Shortcut for <# Writer.Write(expression); ##>

Named Code Blocks:
The general format for named blocks is <#@ BlockName BlockSpecificData #> or <#@ BlockName BlockSpecificData ##>. The second format is used to ignore all white space characters (including the EndOfLine symbol) starting from the ending tag ##> till either the end of line or any non-white space symbol.

Currently the template engine supports two types of named blocks: Imports and InstanceMembers.

The @Imports block is used to import namespaces and, hence, allow C# template code to utilize .NET classes without specifying the full class names. The @InstanceMembers code block includes template methods and properties. It must at least implement the RelativeFilePath property that is declared in the abstract SharpPower.Ate.TextFileGenerator class. This property specifies the name and the relative location of the output file.

Comments:
Comments are normally used to annotate code for future reference or make a part of the template inactive. The template engine does not process anything within the opening and closing comment tags.

Script Block Description
<#-- commented out code or content --#> Makes a part of a template inactive.
<#-- commented out code or content --##>

Makes a part of a template inactive. Ignores all white space characters (including the EndOfLine symbol) starting from the ending tag ##> till either the end of line or any non-white space symbol.

Note: You can find more information about the Active Template syntax in the RapTier documentation.

Although syntax of all Active Templates is the same, RapTier distinguishes 5 different types of templates using the template file name.

Database_XYZ.atcs - Invoked once receiving IDatabase in the Database environment variable.
Table_XYZ.atcs - Invoked one time for every table in the database model. When calling this method, RapTier passes ITable as the Table environment variable.
Procedure_XYZ.atcs - Invoked one time for every stored procedure or function in the database model. When calling this method, RapTier passes IStoredProcedure as the Procedure environment variable. (since RapTier 1.4)
DirectoryInfo.atcs - Used to control the code generation of all templates in the directory (and all the sub-directories) where DirectoryInfo.atcs is located.
XYZ.atcs - RapTier doesn't call this type of templates directly. They are used to store shared static methods and properties used by other templates.

Sample Template

After you have learned the theoretic basics of Active Templates, we can move to the practical part. Let’s create a template that would generate a simple HTML documentation for database schemas.

To create a new template open the "<RapTierRootDirectory>/Templates" directory and create a new directory for your template group, for example SimpleDbDoc. After that you must create the Template.config file that has the following text:

Template.config
<?xml version="1.0"?>
<TemplateConfig>
      <Id>RapTierTutorial.SimpleDbDoc</Id>
      <Name>Simple DbDoc Template</Name>
      <Description>Simple DB documentator.</Description>
      <References>
            <Reference>SharpPower.Ate.dll</Reference>
            <Reference>SharpPower.DbDom.dll</Reference>
      </References>
</TemplateConfig>

Where:

Id - unique template ID
Name - template display name
Description - optional template description
References - a list of the "non-standard" .Net assemblies used by the template script

Usually Template.config files include only two references SharpPower.Ate.dll and SharpPower.DbDom.dll. These references are used by the template engine to compile the templates files to a .NET assembly.

Now let's create your first template file. The template in this example will generate the Default.htm file that displays a list of links to HTML pages with basic table information.

First, we will create a text file named Database_Default.atcs, and enter the code below in it. You can use the source code provided with this article.

Database_Default.atcs
<html>
      <head>
            <title><#= Database.CodeName #></title>
      </head>
      <body>
            <h4><#= Database.CodeName #></h4>
            <ul>
            <# // Iterates through the collection of the table columns
                  foreach(ITable table in Database.Tables)
                  { ##>
                  <li><ahref="<#= table.Name#>.htm"><#=
                  table.Name #></a></li>
            <# } ##>
            </ul>
      </body>
</html>

<#--
The code below imports namespaces and declares methods and properties that are used by the template only. This code will not be copied into the output file.
--##>

<#@ Imports
using System;
using SharpPower.DbDom; /* We need to import this namespace for IDatabase,
ITable and other DB DOM interfaces */
##>

<#@ InstanceMembers
      // Every template must override the RelativeFilePath
      // property to return the name of the output file
      public override string RelativeFilePath
      {
            get { return "Default.htm"; }
      }

      // We don't have to create this property,
      // however it simplifies the template code
      private IDatabase Database
      {
            // RapTier sends IDatabase as the
            // Database environment variable
            get { return (IDatabase)Environment["Database"]; }
      }
##>

As you can see the top part of the code is a mixture of the base output text (in our case this is HTML) and C# code. After that we added an optional comment block. And then two code blocks @Imports and @InstanceMembers.

Second, we need to create a template for generating HTML pages that display table and view details. Create a file and name it "Table_TableInfo.atcs". After that enter the code below and save the changes.

Table_TableInfo.atcs
<html>
      <head>
            <title><#= Table.Name #></title>
      </head>
      <body>
            <h4><#= Table.Name #> Columns</h4>
            <ul>
<#          foreach(IColumn column in Table.Columns)
            { ##>
                  <li><#= column.Name #> (<#= column.DbType #>)</li>
<#          } ##>
            </ul>
      </body>
</html>

<#--
The code below imports namespaces and declares methods and properties that are used by the template only. This code will not be copied into the output file.
--##>

<#@ Imports
using System;
using SharpPower.DbDom; /* We need to import this namespace for IDatabase, ITable and other DB DOM interfaces */
##>

<#@ InstanceMembers
      // Every template must override the RelativeFilePath
      // property to return the name of the output file
      public override string RelativeFilePath
      {
            // Dynamically create the name of the output file
            get { return Table.Name + ".htm"; }
      }

      // We don't have to create this property,
      // however it simplifies the template code
      private ITable Table
      {
            get { return (ITable)Environment["Table"]; }
      }
##>

Now you are ready to test your first RapTier template. Simply run RapTier, connect to a database, in the Template Group combo-box select the SimpleDbDoc template item, and choose the Generate Code menu item from the Project menu.

After the successful generation open the generated project in the Internet Explorer. You've just created your first RapTier template!

Advanced Template Features

Enabled Property
The Enabled property controls whether the template is enabled. The default value is true.

RewriteExistingFile Property
The RewriteExistingFile property is declared in the SharpPower.Ate.TextFileGenerator and used to control whether RapTier rewrites the output file if the file already exists. This property can be overriten in the template. The default value is true.

Database object extended properties
RapTier 1.x templates receive the majority of the code generation settings through the extended properties of the IDatabase interface.

    RapTier supports the following IDatabase extended properties:
  • TargetIDEProperty - The target IDE code. Has one of the following values: VSNET2002, VSNET2003, BDS.
  • DbEngine - The database engine name. Has one of the following values: Generic, MSSQL, Access, FoxPro, Oracle, MySql, SybaseAse, SQLAnywhere.
  • BaseOutputDirectory - The base output directory path.
  • DbTierNamespace - The base namespace for all DB-tier classes.
  • WinUITierNamespace - The base namespace for all WinForm UI classes.
  • WebUITierNamespace - The base namespace for all WebForm UI classes.
  • GenerateWinUI - Specifies whether the WinForm UI code will be generated.
  • GenerateWebUI - Specifies whether the WebForm UI code will be generated.
  • GenerateStoredProcedures - Specifies whether the stored procedures will be generated.
  • GenerateSqlIdentity - Specifies whether the IDENTITY columns are supported.
  • Copyright - Copyright text.
Passing data among templates
In some cases it is necessary to share data among several templates. To accomplish this you can utilize the Session variables ( Environment.Session[<KeyName>] ).

RapTier processes the templates in the following order:
  1. DirectoryInfo.atcs template
  2. Database_Xyz.atcs template(s)
  3. Table_Xyz.atcs template(s)
  4. Procedure_Xyz.atcs template(s)
  5. Templates in the child directories

DirectoryInfo
DirectoryInfo templates don't generate any code. These template files are used to control whether RapTier processes other template files located in the same directory and all sub-directories. RapTier checks the DirectoryInfo Enabled property before processing any other templates. If this property returns true, RapTier gets the RelativeFilePath property value to create the base output directory for all other templates.

Conclusion

This article has demonstated how to create a RapTier template using simple but powerful technology called "Active Templates". If you have any questions regarding the article, please forward them to support@SharpPower.com

Happy Programming!
RapTier team.



© Copyright 2003, SharpPower Corp.. All rights reserved. Site Map