Archive for the 'Code Generation' Category

AjGenesis: Generating the model from assemblies

 Darío Quintana have rewrote his program that generates an  AjGenesis model starting from compiled .NET assemblies. The last version is described at (Spanish post):

Generando con AjGenesis desde los assemblies

The image shows the main project directory content. There are other projects, with NUnit tests, examples, and compiled code.

It is interesting to see how a model (there is no fixed model in AjGenesis) could be obtained from different sources. In a previous post I described a short example, showing how to obtain a model from the database structure:

AjGenesis: Generating the model from the database

Darío, in his post, shows how he uses his project from an AjGenesis tasks:

function GetEntities(path) AssemblyManager.LoadFrom(AjGenesisFromAssemblyPath) obj = new AjGenesis.FromAssembly.Collector() list = obj.GetEntities(path,null) return list end function

This code uses the new AssemblyManager to load the library AjGenesis.FromAssembly.

The classes Model, Entity, Property are the model, like in other AjGenesis examples. The class Collector creates a Generator object. This object is in charge of the hard work, finding the entities inside an assembly:

using System.Collections; namespace AjGenesis.FromAssembly { public class Collector { public ArrayList GetEntities(string assemblyPath, string ns) { Generator g = new Generator(); g.Path = assemblyPath; g.AssemblyToObjects(); ArrayList array = new ArrayList(); foreach (Entity entity in g.Model.Entities) { array.Add(entity); } return array; } } }

Un fragmento de Generator:

 

public void AssemblyToObjects() { Assembly assembly = Assembly.LoadFrom(Path); Type[] types; types = assembly.GetTypes(); //Get all types from the assembly for (int i = 0; i < types.Length; i++) { //Veo que interfaces está implementando bool ImplementaIEntity = false; Type[] interfacesTypes = types[i].GetInterfaces(); ImplementaIEntity = true; if (ImplementaIEntity) { Entity entity = new Entity(); entity.Name = GetTypeName(types[i].Name); entity.FullName = types[i].FullName; if (types[i].BaseType != null) { entity.Inherits = GetTypeName(types[i].BaseType.Name); entity.InheritsFullName = types[i].BaseType.FullName; } PropertyInfo[] propertyInfo = types[i].GetProperties(); foreach (PropertyInfo pi in propertyInfo) { Property prop = new Property(); prop.Name = pi.Name; prop.TypeName = pi.PropertyType.Name; if (pi.PropertyType.FullName != null) { prop.TypeFullName = pi.PropertyType.FullName; } else prop.TypeFullName = string.Empty; entity.Properties.Add(prop); } _model.Entities.Add(entity); } } }

This is only a fragment of the code, see the complete project to have more detail. It uses reflection to obtain the types in an assembly, and its properties. I guess Darío wants to improve the way of detecting when a type is an entity, using interfaces and attributes.

Angel “Java” Lopez
http://www.ajlopez.com/

AjGenesis: Generating the model from the database

My code generation project AjGenesis uses one or many user-defined models to generate text artifacts, using programmable tasks and templates. When I started the project, I read the Kathleen Dollard’s book Code Generation in Microsoft .NET

One of her recommendations is take metatadata from some resource, like a database. In my opinion, not all needed metadata resides in a database schema, so, from the very beginning of the project, I follow the way of a free user-defined model (I quickly go away from the Dollard’s ideas of using XSLT transformations: I think XSLT is the devil’s work… don’t try it at your home..;-). There are many interesting points her ideas, I should write a post about her book.

But metadata from database is not discarded. It can be used, applying some work. Remember: code generation is a pragmatic solution, don’t ignore useful metadata source.

So, some months ago, I wrote a simple example inside the ones that come with AjGenesis. You can try the example, downloading the last published version of the project:

AjGenesis Versión 0.5

The example is located at examples\LoadDB directory.

It works using the Northwind database that comes as example for MS SQL Server. In the directory example, from the command line, execute

make

This command executes an AjGenesis task:

..\..\bin\AjGenesis.Console Tasks\DbProcess.ajg
pause

It connects with database:

PrintLine "Connection" AssemblyManager.LoadWithPartialName("System.Data") con = new System.Data.SqlClient.SqlConnection() PrintLine "ConnectionString" con.ConnectionString = "server=(local);uid=sa;database=Northwind" PrintLine "Command" cmd = new System.Data.SqlClient.SqlCommand() cmd.Connection = con cmd.CommandText = "select * from Information_Schema.Tables" con.Open()

This code uses the information inside Information_Schema.Tables. Take notice of the use of the new AssemblyManager, an utility in AjGenesis that loads assemblies.

Then, the code obtains the table names:

dr = cmd.ExecuteReader() TableNames = new System.Collections.ArrayList() while dr.Read() PrintLine "Table " & dr.Item("Table_Name") & ": " & dr.Item("Table_Type") TableName = dr.Item("Table_Name") if dr.Item("Table_Type")="BASE TABLE" then TableNames.Add(TableName) end if end while dr.Close()

Once this info was obtained, it gets the columns of the tables, making an in-memory model in a Tables collection:

Tables = new System.Collections.ArrayList() For each TableName in TableNames PrintLine "Loading Table " & TableName Table = new AjGenesis.Models.DynamicModel.DynamicObject() Table.Name = TableName Table.Columns = new System.Collections.ArrayList() cmd.CommandText = "SELECT * from Information_Schema.Columns where Table_name='" & TableName & "'" dr = cmd.ExecuteReader() while dr.Read() ColumnName = dr.Item("Column_Name") PrintLine "Processing Column " & ColumnName & ": " & dr.Item("Data_Type") Column = new AjGenesis.Models.DynamicModel.DynamicObject() Column.Name = ColumnName Column.DataType = dr.Item("Data_Type") if dr.Item("Character_Maximum_Length") then Column.Length = dr.Item("Character_Maximum_Length") Column.IsNumeric = false else if dr.Item("Numeric_Precision") then Column.Length = dr.Item("Numeric_Precision") Column.Scale = dr.Item("Numeric_Scale") Column.IsNumeric = true end if end if Column.SqlName = Column.Name Column.Name = Column.Name.Replace(" ","") Table.Columns.Add(Column) end while dr.Close() Table.SqlName = Table.Name Table.Name = Table.Name.Replace(" ","") Tables.Add(Table) end for

Finally, I use the old trick of visiting the model, applying a template to it to generate other model. This is an interesting idea that deserves more attention: multi-step model generation and transformation. I could inject some expert system to complete the model, and infers any missing part. The model can be a in-memory one, or it can saved in an XML file, to be adapted and improved:

FileManager.CreateDirectory("Model") for each Table in Tables TransformerManager.Transform("Templates\Table.tpl", "Model\${Table.Name}.xml", Environment) end for

A generated model as example:

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <Table> <Name>Region</Name> <SqlName>Region</SqlName> <Columns> <Column> <Name>RegionID</Name> <SqlName>RegionID</SqlName> <DataType>int</DataType> <Length></Length> <Scale></Scale> </Column> <Column> <Name>RegionDescription</Name> <SqlName>RegionDescription</SqlName> <DataType>nchar</DataType> <Length>50</Length> <Scale></Scale> </Column> </Columns> </Table>

Now, using AssemblyManager, we can load any .dll assembly, and use it to generate any code. Darío Quintana works with this feature to generate code from compiled code (post in Spanish Generando con AjGenesis desde los assemblies). You can download his utility from

http://code.google.com/p/darioquintana/downloads/detail?name=AjGenesis.FromAssembly.7z

One idea: we can use the Meta library from MyGenerationSoftware to obtain metadata from any supported database. Notably, now this utility has published source code.

Angel “Java” Lopez
http://www.ajlopez.com/en

Code Generation as a Service with AjGenesis

I’m back! I want to write in this post about the new features I’ve added to my code generation project AjGenesis. The main points are:

- A new interactive way to use it, a web based application

- Examples with that new interface, to generate C#, VB.Net, Java and PHP applications, all from the same abstract model

These features were published last January at release 0.5 in CodePlex

Using AjGenesis

Years ago, I began to work in this project. Those days, the only way to execute and use it were the console, with commands. Later, I adopted NAnt, and NAntGui, as interfaces to launch the system and execute tasks and transformations. The project can be used as a set of .DLLs, referenced from custom application. Carlos Marcelo Santos has published posts (in Spanish) about how to use AjGenesis from NAnt

Cómo generar código con AjGenesis sirviéndonos de NAnt
Cómo generar código con AjGenesis sirviéndonos de NAnt - Parte II

Last year, 2007, Jonathan Cisneros wrote a great Windows interface, named AjGenesis Studio:

AjGenesis Studio: una IDE para AjGenesis
AjGenesis Studio at CodePlex

As an exercise at the end of year 2007, I wrote a new project in the original solution, and I published last January inside the last release 0.5 at CodePlex.

It’s a new web project, that I called, inspired by the work of Jonathan, AjGenesis Web Studio

The main point is, with this project, to show that the functionality from the AjGenesis core can be used and exposed in our applications, this time from a web interface, using ASP.NET. With this approach, we can put a server in our internal network or at Internet, and create, edit, upload and download user defined models, generate source code, and download the results. We could call this, Code Generation as a Service.

Let’s look the project, its functions and some inners.

The project

It’s a web project, named AjGenesis.WebStudio.

To launch it, load the AjGenesis.sln solution (located at src directory inside the version 0.5 from CodePlex) with Visual Studio 2005, and build the complete solution.

(If you have errors in the AjGenesis.WebStudio project, probably you must add a reference to a .DLL that manages the file compressions. Add as reference to the project the file src\Libraries\Ionic.Utils.Zip.dll. This library generates .zip files, and expand them).

In the web solution, I used Master Pages, and a default Theme. It doesn’t manage a database, only files and directories. We’ll see below that the project has a mini wiki, to write help pages that can be defined by the user.

The look and feel is simple, but you can change the theme and master page to obtain a better result.

The system can generate code in the fly, and download it as a .zip file. You can use the classic AjGenesis system, as I explained in past post, but now, we can use it from any browser. You don’t need .NET in your client machine, and you can work from other operating systems.

After the build of the solution, click right mouse button on the file \Default.aspx in project AjGenesis.WebStudio, and choose View in browser…:

This is preferred to launch the project in debug mode: if you debug the project, it will execute the code generation task in very slow way.

Working Directory

The system uses a working directory, with a structure that resembles the examples at AjGenesisExamples3.zip (to download from examples at CodePlex). The default working directory is AjGenesis.WebStudioWorkingDirectory:

Some directories:

Projects: There is a directory here for each project model.
Templates: Containing the template files to process during the code generation phase
Build: The code generated code resides in this directory.

The working directory can be changed using the left menu option Working Directory and then, choosing the option Change Working Directory:

Generating Hello World

As I used to comment in my speeches, the acid test of all code generation system is to help us to model and produce the most simple and universal software system, the reknowed Hello World example. There is an explanation on how to do this with classic AjGenesis in my post

Code Generation with AjGenesis- A Hello World application

In AjGenesis Web Studio, select the left menu option Generate. This is the result page

There are two dropdown list. We’ll see how they are filled. At the first list, there are the defined projects:

Choose HelloWorld. Then, go to technology list, showing:

In this project, only Java and Net20 are the defined technologies. Other projects have more technologies. Choose Java and the press the Generate button. After a while, the page shows a result.

How this works?

First point, the system manage a working directory, the default is AjGenesis.WebStudioWorkDirectory, a syster directory of the web project. There is a Projects project, cointaining more directory, each one is a project for the system.

The directory AjGenesis.WebStudioWorkDirectory\Projects\HelloWorld has a Project.xml file that describes the free model we use in this case:

<Project> <Name>HelloWorld</Name> <Description>HelloWorld Example</Description> <GenerateTask>GenerateHelloWorld</GenerateTask> <Message>Hello World</Message> </Project>

Inside the directory project, there is a Technologies directory. Each XML file that is found there it’s managed as a technology model in the system. Again, as I explained in my posts on AjGenesis , this file has a free model, you can put here anything to process from code generation process. The concepts of project and technology is not mandatory, but AjGenesis Web Studio takes them as special directories, and read them to obtain the list of project and associated technologies.

The technology Java.xml file contains:

<Technology> <Name>Java</Name> </Technology>

and Net20.xml contains:

<Technology> <Name>Net20</Name> </Technology>

Nothing special. The value Name inside Technology drives what steps to execute during code generation phase.

After press the generate button, the system loads the project and technology model in memory. Then, it executes the file GenerateCode.ajg located in directory Tasks. But if the project file contains a  GenerateTask tag, as in this project, that file is executed instead the default one. This is the content of Tasks\GenerateHelloWorld.ajg:

 

PrintLine "Generating HelloWorld..." if not Project.BuildDir then Project.BuildDir = "${WorkingDir}Build/${Project.Name}" end if if not Project.Title then Project.Title = Project.Name end if if not Project.Version then Project.Version = "1.0.*" end if if not Project.Language then Project.Language = "en" end if if not Project.SystemName then Project.SystemName = Project.Name end if PrintLine "Creating Directory ${Project.BuildDir}" FileManager.CreateDirectory("${Project.BuildDir}") Include "Tasks\BuildHelloWorld${Technology.Name}.ajg"

This file is written in an scripting language, a pillar of AjGenesis, affectously named AjBasic. The Project variable is the representation in memory of the tag <Project> loaded from the Project.xml file, described above. In memory, it is as an object, with properties. It’s not an static object: you can add properties in runtime, as Project.Version in the above text. If in an if sentence we asks the value of  Project.Version and this doesn’t exist, it’s not an error, the result is simply Nothing and that value is treated as false for boolean evaluations (like in other languages, notably PHP).

Finally, the last line includes an additional file to process dinamically. The string contants in AjBasic have expression expansion: all between ${ and } is evaluated. Using the value of Technology.Name (obtained from loading in memory the XML technology file), it executes BuildHelloWorldJava.ajg or BuildHelloWorldNet20.ajg. The first one contains the steps to generate a .java file:

<# PrintLine "Generating Solution ${Project.Name}" if not Project.Title then Project.Title = Project.Name end if if not Project.Version then Project.Version = "1.0.*" end if PrintLine "Creating Directories" FileManager.CreateDirectory("${Project.BuildDir}") FileManager.CreateDirectory("${Project.BuildDir}\${Technology.Name}") TransformerManager.Transform("Templates\HelloWorld\ClassJava.tpl", "${Project.BuildDir}\${Technology.Name}\HelloWorld.java", Environment) #>

This code uses inner AjGenesis utilities that create directories and expand a template file. ClassJava.tpl contains:

// // Automatically generated by AjGenesis // http://www.ajlopez.com/ajgenesis // public class HelloWorld { public static void main(String[] args) { System.out.println("${Project.Message}"); } }

All this produces the directory Build\HelloWorld\Java:

If we choose the Net20 technology, more files would be generated:

This is a more complete result. It has a VS 2005 solution file, two project directories, one in VB.NET and the other in C#, with source code and project files:

To see the generated code, its files and directories, go to left menu option Builds:

There is a directory for each project. You can download a complete directory, as a .zip file. We can create a file, download a directory, upload and expand a .zip file, and consult a help page. We can read, edit, and delete each file, in this case readme.txt.

Go to the View at HelloWorld directory:

You can browse directories, upload and download files. You can move a directory, or make a copy, to experiment without loosing the original content.

Generating C# and VB.NET solutions

After this simple example, let’s go for more. For more information about the next examples and their models, read:

Application Generation using AjGenesis

Go again to left menu Generate option. Now, we choose a project, AjSecondExample. Its technology list is more complete:

Choose CSharp2 and generate. This process creates a complete solution inside Builds\AjSecondExample\CSharp2. There is an Sql directory with DDL script to create a MS SQL Server database. Inside the Src directory, you’ll find the solution, composed of a set of projects:

This projects follows a layered archictecture, that you can modify from the templates. They use a data access layer, based on my AjFramework project, but you can change to access Enterprise Library or your own data services.

You must create the database using the generated scripts, and modify the connection string in the web.config to match your environment. The application can be compiled and executed:

The administration page shows:

Back to generate page, execute the VbNet2 technology, obtaining a directory with the same structure, now with Visual Basic.NET code:

All these depend of the specified technology inside the files at Projects\AjSecondExample\Technologies. The content of VbNet2.xml is:

<Technology> <Programming> <Dialect>VbNet2</Dialect> </Programming> <Database> <Dialect>MsSql</Dialect> <Name>AjSecondExample</Name> <Username>sa</Username> <Prefix>ajse_</Prefix> <Host>(local)</Host> </Database> </Technology>

and CSharp2.xml:

<Technology> <Programming> <Dialect>CSharp2</Dialect> </Programming> <Database> <Dialect>MsSql</Dialect> <Name>AjSecondExample</Name> <Username>sa</Username> <Prefix>ajse_</Prefix> <Host>(local)</Host> </Database> </Technology>

These data are used during the code generation process.

Note: inside Tasks\BuildTechnology.ajg file, you’ll find a new variable, injected from the web project:

if not Project.BuildDir then Project.BuildDir = "${WorkingDir}Build/${Project.Name}/${Technology.Programming.Dialect}" end if

This is the WorkingDir variable that points to the working directory we selected in AjGenesis Web Studio.

Genarating Java and JSP applications

Many projects (AjFirstExample, AjSecondExample, AjTest….) can be generated in Java with JavaServer Pages. A build.xml file is generated to be modified and used to compile the generated code using the ant utility (you can use this file from an IDE, like Eclipse or NetBeans).

The target build  makes a .war deploy file. You can browse and modify the build.xml file to install the .war in a Tomcat web container.

The generated code is composed of .jsp files (web pages in Java) and Java code to compile that implements a service layer and a data access layer, exchanging simple JavaBeans between layers. The DDL script, in these examples, is a MySql one.

If you build and deploy the application, and install the database in a MySql server, you can see it working fromn a Tomcat server:

Generating application using Domain-Driven Design ideas and Hibernate, NHibernate

Many example projects (AjFirstExample, AjSecondExample, AjTest…) have defined technologies CSharp2DDDNh, JavaDDDHb, VbNet2DDDNh, and even VbNet2Nh. The DDD ones implement some concepts from Domain-Driven Desigg, as Application, Domain and Infrastructure layer, but the templates could be improved. The *Nh projects generate code for entities using NHibernate mapping. The *Hb projects use Hibernate.

An example of NHibernate generated mapping:

 

<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"> <class name="AjFirstExample.Domain.Customer, AjFirstExample.Domain" table="ajfe_customers"> <id name="Id" column="Id" type="Int32" unsaved-value="0"> <generator class="native"/> </id> <property column="Name" type="String" name="Name" length="255"/> <property column="Address" type="String" name="Address" length="255"/> <property column="Notes" type="String" name="Notes" length="255"/> </class> </hibernate-mapping>

These solution can be built as the previous examples. You’ll see better generator templates for NHibernate in the AjOmar example at CodePlex. Post (in Spanish) explaining the process at

Generando código para NHibernate (Parte 1)
Generando código para NHibernate (Parte 2)
Generando código para NHibernate (Parte 3)

Generating PHP applications

If you choose PHP technology, web page with PHP code are generated, using MySql as database. The generated code can be copied to a directory in a web site that supports PHP, Apache, or IIS. AjTest example running in a IIS with PHP4:

Other directories

In the working directory, there are other directories:

SourceCode: Containing some source code that is copied into the solution during code generation.

Libraries: Additional .dlls, to copy and use in the generated applications.

The larger subdirectory  is Templates:

In previous posts I described in detail the creation and use of a template file. This is the content of a template that generate a C# entity:

<# rem Entity Generator rem for C Sharp include "Templates/CSharp2/CSharpFunctions.tpl" message "Processing Entity ${Entity.Name}" include "Templates/CSharp2/Prologue.tpl" #> /* * Project ${Project.Name} * ${Project.Description} * Entity ${Entity.Name} * ${Entity.Description} * */ using System; namespace ${Project.SystemName}.Entities { public class ${Entity.Name} { // Private Fields <# for each Property in Entity.Properties message "Processing Field ${Property.Name}" #> private ${CSharpType(Property)} ${CSharpFieldName(Property)}; <# end for #> // Default Constructor public ${Entity.Name}() { } // Public Properties <# for each Property in Entity.Properties message "Processing Property ${Property.Name}" #> public ${CSharpType(Property)} ${Property.Name} { get { return ${CSharpFieldName(Property)}; } set { ${CSharpFieldName(Property)} = value; } } <# end for #> } }

Help pages

I’m testing some ideas in this web project. There are code to create “wiki” pages, that can be used as help pages in the system.

You can edit this kind of pages:

There is a way to insert links to other wiki pages and to external ones. The page data is represented as a .NET object in memory, and that object is serialized in an XML file in Pages application directory. There is no database to store page: each one is an object, serialized in a .xml file.

Conclusions

I hope this system helps to a better understanding of AjGenesis project features and potential. With a more user friendly interface, the project can be used by more people. We can generate code from command line, or using NAnt utility, or AjGenesis Studio.

I ever remark a point: all these are examples, AjGenesis is not limited to generate only this kind application. You are in charge: you can define the model that matches your project requirements, using any technology you choose. You can codify DDD ideas in a different and better way. You can generate Hibernate/NHibernate mappins using other patterns and mapping idioms. You can use other ORM utilities, and generate code for them. You can generate PHP5 pages that use Prado, instead of plain PHP4. You can generate stored procedures for Oracle, instead of my examples that use MS SQL Server. Or write better ones. You can generate WinForms code, instead of ASP.NET page. You can generate JavaServer Faces pages, views, beans, and abandon JavaServer Pages. You can generate the code or text you want: e.g., unit tests, or documentation pages. I recommend that the generated code resembles the code you could generate manually.

I invite anyone that uses this system, to post his/her work, or leave comments here. You can participate in the Spanish list:

http://groups.google.com/group/codegeneration?hl=es

Next steps

Back to develop, I have some ideas:

- Improve the templates to generate more technologies, as VS 2008 projects, solutions, templates for Struts 1/2, Spring, better mapping for Hibernate, NHibernate, and code generation for the new ASP.NET MVC.

- Write posts about these templates

- Publish the new examples

- Write down a useful documentation (now, it’s minimal: you can found more details in this posts)

Enjoy the project!

Angel “Java” Lopez
http://www.ajlopez.com/en

Genesis Studio: an IDE for AjGenesis

Thanks to the excellent work of  Jonathan Cisneros, now we have an IDE to use with AjGenesis. Developed with CSharp2, it edits projects, model and template files, even with syntax color!!.

It’s an application, ready to use, without rough edges. It will evolve: Jonathan has some ideas for extensions, to complete its program.

You can download Genesis Studio from the group Code Generation page:

Code Generation Google Groups

or you can try this link. In that group there are many files to download, with new templates, models and examples. Genesis Studio is at:

It comes with source code, in a Visual Studio 2005 solution. It’s compilation is easy, it have all the required libraries:

With this application we can edit a project directory, its entities, model, technologies. Remeber, AjGenesis has a free model that you can define for each project. Genesis Studio can read and edit template ant task files.

Some options:

When you choose a project directory, a project explorer appears, showing folders and content:

XML, templates and task files have sintax color support:

 

My thanks to Jonathan Cisneros, for this useful application.

Code generation is technique that has power uses. In an technology change environment, with complex application, it is important to delegate the menial and repetitive tasks to the software itself.

Angel “Java” Lopez
http://www.ajlopez.com/en

Recipes with AjGenesis

Past weeks, I was giving speechs about my open source code generation project, AjGenesis, at two cities of my country: Tandil and Corrientes, thanks to the organization of the Microsoft User Group of Argentina. Usually, I show examples of my project in action; following the “dog fooding” principle, I used it every week. The current version under development is

AjGenesis 0.5

More about the capabilites of the project at:

Application Generation using AjGenesis
Code Generation with AjGenesis: A Hello World application

I’m experimenting adding the capability of invoking one or more entry windows, from a task, to take parameters from the user during the code generation process.

Now, all is produced from model or models, free designed by users, serialized on XML files. But it could be convenient, depending of the code to generate, to take new parameters from the user, in the middle of the code generation. Examples of parameters: target directory and file names, connection strings, namespaces and packages names, etc…

Following this idea, there is a new experimental project in the solution, named AjGenesis.Recipes,  that use the new project AjGenesis.UI. This UI project has a window form dedicated to accept data from the user.

An screenshot:

At the beginning, there is no information in the tree at left. Go to File | Open… and select an example file with recipe definitions: Recipes.xml (it is in the source code directory of the project).

This file contents:

 

<?xml version="1.0" encoding="utf-8" ?> <Recipes Name="Recipes"> <Node Name="Hello World"> <Recipe Name="Hello World VB.NET Module" Task="Tasks/HelloWorldTask.ajg" Documentation="Tasks/HelloWorldTask.html"/> </Node> <Node Name="VB.NET"> <Recipe Name="Entities" Task="Tasks/Task1.ajg" Documentation="Tasks/Task1.html"/> <Recipe Name="Services"/> </Node> <Node Name="CSharp"> <Recipe Name="Entities"/> <Recipe Name="Services"/> </Node> </Recipes>

Each  node can contains nodes and recipes. A recipe has a name, that is displayed in the tree, a task, AjBasic code to execute, and a file that documents the recipe in HTML.

If you double click over the Hello World VB.NET Module recipe, a window appears. You can enter the file to use as a model, and the name of the .vb file to generate:

The new feature is implemented in the task file, that uses the project AjGenesis.UI and its window form. Let see Tasks\HelloWorldTask.ajg:

form = UIManager.CreateInputForm() form.Text = "Class Generator Wizard" form.AddFileField("Model","Model to use","") form.AddFileField("FileName","File to Generate","") n = form.ShowDialog() if n = 1 then ModelFile = form.GetField("Model") FileName = form.GetField("FileName") ModelManager.LoadModel(ModelFile,Environment) TransformerManager.Transform("Templates/HelloWorldVb.tpl",FileName,Environment) end if

UIManager is a new manager object in this AjGenesis version. Note how a window and its field can be defined and processed. The field values can then retrieved, to use in the generation process.

This is work in progress, but it looks enough interesting to me to write this post.

The model is still used. Any recipe needs one or more model to use as a base to produce the code or text to generate. With AjGenesis Recipes the model could be given in a interactive way. The time will show if these feature is useful to the users, instead of the use of NAnt tasks.

A recipe could be written, without using a model: the paremeters could be enough  to feed the process.

Using a more elaborate interface, we could define our own files of tasks, recipes and templates, invoked from thise program. We can write a recipe to generate all the DAOs in a systems. Or a recipe that generates a set of entities..

Next steps:

  • Estabilization of code (I must fix some directory and file name treatment, their relative position)
  • Improve exception management
  • Capture the output of tasks, and show it in one window during the process 
  • Complete AjGenesis.UI to manage a more complete set of controls (now, it only has a text field, and a directory or file chooser) and a list of windows, like a real wizard
  • Allow the use of user defined controls and windows
  • After writing some recipes, explore if it is useful or interesting or feasible, to integrate this stuff into Visual Studio (or Eclipse, why not), as GAT, or like a  Visual Studio Integration Package.

Suggestions, comments, ideas, welcome!

Angel “Java” Lopez
http://www.ajlopez.com/en

Preserving Code in AjGenesis

One of the issues to resolve when we use a code generation engine, is how to add our own code to a generated source file, without loss it in the next generation phase. Sometimes, we generate code only as a one-off activity, and modify the code without worry about a new generation, but in other situations, we use code generation many times. In this case, it would be great to have the capability of preserving manually added code.

During the past month, I added that functionality to my open source code generation engine AjGenesis. Thanks to the spanish group grupo de generación de código, and all its members that tested the new feature.

You can use it since version 0.5:

AjGenesis 0.5

to download from CodePlex.

An example

In that version, under directory examples\HelloPreserve, there is an example of preserving code.

The sample is generated from command line, entering

make

that invokes a .bat file containing:

..\..\bin\AjGenesis.Console Model.xml Build.ajg

This command loads a model of a  Hello World application, from Model.xml:

<Project Name="HelloWorld">
<Messages>
<Message>Hello</Message>
<Message>World</Message>
<Message>Again</Message>
</Messages>
</Project>

(You can read a detailed description of this kind of simple model in a previos post:

Code Generation with AjGenesis: A Hello World Application

A more advanced example at

Application Generation using AjGenesis

)

The make command invokes a small program written in an interpreter, AjBasic. The file is Build.ajg:

PrintLine "Generating HelloWorld" 

TransformerManager.Transform("ModuleVb.tpl", "HelloWorld.vb", Environment, "PRESERVE") 

There is something new: the third parameter in Transformer.TransformTransformer is a helper object, that is implanted in the variable environment of AjGenesis, that is accesible from AjBasic programs. Using this object we can invoke the template engine. It has a method Transform with two parameters: the file nam of the template to process, and the name of the file to generate. In this new variant, there is a third parameter, that is used as a mark to delimitate a code preserving block inside the template.

This is the example template, ModuleVb.tpl:

'
' Project ${Project.Name}
' Automatically generated by AjGenesis
' http://www.ajlopez.com/ajgenesis
'

' PRESERVE comment start

' PRESERVE comment end

Module Module1 

    Sub Main()
        System.Console.WriteLine( _
<#
    n = 0
    for each msg in Project.Messages
        if n then
            Print "& "
        end if
        n = n + 1
#>
        "${msg}" _
<#
    end for
#>
        )
    End Sub 

' PRESERVE code start

' PRESERVE code end

End Module 

All in this code that contains the mark PRESERVE (that is, the third parameter passed to Transform method), until other line containing the same mark, it will be preserve during code generation.

NOTE: the algorithm matches the lines using the full content of the first line in the preserving block. That is, if the template contains a line:

‘ PRESERVE comment start

this is the line that is searched inside the original code, in order to preserve the block. The blocks to preserver are identified by the FULL CONTENT of the line that initiates each block.

Later, if you modified the generated code, adding text to that blocks, that text is preserved:

'
' Project HelloWorld
' Automatically generated by AjGenesis
' http://www.ajlopez.com/ajgenesis
'

' PRESERVE comment start

' This is my comment two

' PRESERVE comment end

Module Module1 

    Sub Main()
        System.Console.WriteLine( _
        "Hello" _
&         "World" _
&         "Again" _
        )
    End Sub 

' PRESERVE code start

    Sub MyMethod()
        Console.WriteLine("My own inmortal method")
    End Sub 

' PRESERVE code end

End Module 

Some points

Let’s review some points in this process. Why we must indicate a parameter as mark? Why not simply use a predefined mark? First, to maintain compatibility with previous templates. But, more important: you decide what is the mark to use to identify code to preserve. You can use different marks in each project or type of generated text file. You are in charge.

If you want to explore how this feature is implemented, you can examine the file Utilities\FileMerger.vb in project AjGenesis.GenericTransformer. In short, that code apply the transform to the template, generates a temporary file, and merge it with the previous file (I use a temp file, so, in case of any errors during the transform, you can read the generated code so far). Then, it merge the new file with the old one. The preserving code are determined by the supplied mark and the full content of its first line.

I hope you find this feature useful. I’m sure that we can apply our knowledge about application building in a smart way: delegating repetitive and menial tasks to software.

Angel “Java” Lopez
http://www.ajlopez.com/en

Application Generation using AjGenesis

These days, I wrote new examples for my open source project AjGenesis

http://www.ajlopez.com/ajgenesis
http://www.codeplex.com/ajgenesis

Using AjGenesis, we can produce, starting from our own model, applications for ASP.NET 1.x/2.x, JSP, using SQL Server in .NET, with ADO.NET or NHibernate, or MySql with Java and Hibernate. The sample generated applications use a layered architecture (but remember: these are sample applications, you can write and use your own models, tasks, and templates). Other option: it can generate layers following ideas from Eric Evans’ Domain-Driven Design.

I’m still writing those examples, but now, you can download the current version from

AjGenesisExamples3New.zip

The examples require the use of AjGenesis last release:

AjGenesis Version 0.4.3

but you can try the current version under development:

AjGenesis Version 0.5

In this post, I want to comment how AjGenesis works and some of its inner structure, using one of those examples. Although I will concentrate in producing VB.NET code, you’ll find that the example is able to produce C Sharp and Java/JSP solutions, as well.

First, let’s review first some points about the project. The big picture:

AjGenesis Version 0.4.3 is written using VB.NET V1.x, but version 0.5 is the current version under development, and it was rebuilt using .NET 2.0. The project is open source, and has a BSD-like license, that allows to use it in any project what you want: you only need to comply with the license (in short, put some reference to the original project). It is possible to be used like a library, invoked from your own project, or it is possible to be invoked from command line, or even it can be used from using NAnt (this tool gives you a better organization of the code generation tasks).

There are several samples in the page of the project (inside the project zip source file and in additional files). They generate code from a model, invoking tasks and processing templates. The samples generate code PHP, Java, JSP, VB.NET, C#, ASP.NET, and even scripts of procedure and data base stored. I want to emphasize two points:

- The model to use is totally definible by you. It’s a free model, it’s not a fixed one. You can model what you want to model.

- The tasks and templates to apply are totally programmable and controlable. You are in charge. 

That’s make a difference from other generators. We can create our own model, and its own templates and tasks, to generate any text artifacts. Other systems start from the data base, and they only generate a group of predefined text files (as POJOs, plain old java objects, or DAOs, Data Objects Access). But with AjGenesis you can generate any text file you need.

In order to better understandind the free model concept, read a previous post:

Generating Code Hello World with AjGenesis

In that post, the initial steps are described, using a free model, totally oriented to the domain to represent: a typical Hello World application, implemented in different technologies.

Creating an application

Let’s do something more complete in this post. Suppose we need to create a simple solution simple, with two tables, in a MS SQL Server databse, source code in VB.NET 2,0, web interface, layer of services, layer of data, business components and business entities a la Microsoft. We want to generate the solution, the projects, scripts for database creation, and stored procedures. This example is included in the examples AjGenesisExamples3New.zip. First step: to write the model.

The project

In a directory of projects of the examples that accompany this article, there is a Projects/AjFirstExample directory.

In that directory it is the Project.xml file that contains the model.

<Project>
    <Name>AjFirstExample</Name>
    <Description>First Example
    using AjGenesis</Description>
    <Prefix>AjFE</Prefix>
    <Domain>com.ajlopez</Domain>
    <CompanyName>ajlopez</CompanyName>
    <Model>