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:
-
DirectoryInfo.atcs template
-
Database_Xyz.atcs template(s)
-
Table_Xyz.atcs template(s)
-
Procedure_Xyz.atcs template(s)
-
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.
|