Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating RapTier Templates

0.00/5 (No votes)
14 Dec 2003 2  
Gives an insight in the design of RapTier templates, and demonstates the steps you need to take to create your own template.

RapTier - .NET Code generation tool

Introduction

The purpose of this article is to provide a look "under the hood" of RapTier 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#.

Background

Prerequisites

  • .NET framework 1.0 or 1.1. Please follow this link "How to get the .NET Framework" to download the .NET framework.
  • RapTier. If you don't have RapTier installed, please download it here. (Free edition available).

What RapTier is

RapTier is a template-based C#, VB.NET and SQL Code Generator that allows developing powerful and robust database-driven .NET applications in minutes.

Unlike many other code generation tools that use "passive" templates with a limited set of tags replaced during generation, RapTier utilizes Active Templates (AT) technology. An Active Template is a mixture of static code and C# instructions that control the way the code is generated. By using/modifying existing or creating new templates, you are able to generate code that meets your specific development requirements.

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 TwoLKit.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 TwoLKit.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 will 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, create the Template.config file.

The file structure must look like this:

Next open Template.config and copy the code below in it.

<?xml version="1.0"?>
<TemplateConfig>
        <Id>RapTierTutorial.SimpleDbDoc</Id>
        <Name>Simple DbDoc Template</Name>
        <Description>Simple DB documentator.</Description>
        <References>
            <Reference>TwoLKit.Ate.dll</Reference>
            <Reference>TwoLKit.nTierBuilder.Api.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 file include only two references TwoLKit.Ate.dll and TwoLKit.nTierBuilder.Api.dll. These references are used by the template engine to compile the template files to a .NET assembly.

Now let's create our first template. 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 TwoLKit.nTierBuilder.Api.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
        // and allows i.e. using <#= Database.CodeName #>
        // instead of <#= 
        //((IDatabase)Environment["Database"]).CodeName #> 
        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 TwoLKit.nTierBuilder.Api.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
            // and allows i.e. using <#= Database.CodeName #> instead of
            // <#= ((IDatabase)Environment["Database"]).CodeName #>
            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 (supported databases: MS SQL Server, MSDE, MS Access, Oracle, MySQL), 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 Internet Explorer. You've just created your first RapTier template and generated a database-driven application!

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 TwoLKit.Ate.TextFileGenerator and used to control whether RapTier rewrites the output file if the file already exists. This property can be overwritten 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, Oracle, MySql.
    • BaseOutputDirectory - The base output directory path.
    • DbTierNamespace - The base namespace for all DB-tier classes.
    • WinUITierNamespace - The base namespace for all WinForm UI classes. (since RapTier 1.4)
    • WebUITierNamespace - The base namespace for all WebForm UI classes. (since RapTier 1.4)
    • GenerateWinUI - Specifies whether the WinForm UI code will be generated.
    • GenerateWebUI - Specifies whether the WebForm UI code will be generated. (since RapTier 1.4)
    • GenerateStoredProcedures - Specifies whether the stored procedures will be generated. (since RapTier 1.4)
    • GenerateSqlIdentity - Specifies whether the IDENTITY columns are supported. (since RapTier 1.4)
    • 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

In this article, we examined the structure of RapTier templates. The ASP.NET-like syntax used in the templates allows to grasp and apply the technique very quickly. All templates provided with RapTier can be used "as is" or extended and customized to fit your standards and requirements.

For the purpose of this article, I tried to keep the logic of the "SimpleDbDoc" template, simple. Feel free to extend the template further, or check out "DbDoc" - a template that generates a complete database documentation in HTML format.

Happy programming!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here