Angel \”Java\” Lopez on Blog

May 29, 2012

AjGenesis Code Generation in .NET, Javascript and Ruby, All the Gates are Open

Usually, I get up early in the morning. Today, I got up a bit earlier, with some ideas about how to implement a simple template engine for my personal project, AjGenesis in Ruby. Then, I put my hands at work, and 3 hours later I had a solution, built using TDD (I made frequent commits, so you can see the progress of development in the GitHub Log).

The result at my GitHub account:

https://github.com/ajlopez/AjGenesisRb

Initially, I planned to use one of the template engines already available in Ruby, like Haml. But I decided to write my own implementation. Past week, I wrote AjGenesis in Javascript/NodeJs, see:

https://github.com/ajlopez/AjGenesisNode

In that project, I separated the template engine in another package:

https://github.com/ajlopez/SimpleTpl

In this way, I designed the template format to be similar to the original templates in classic AjGenesis.

I reuse the Javascript template engine in another new project (code kata of the past weekend):

https://github.com/ajlopez/SimpleMvc

a simple MVC implementation over NodeJs/Express.

So, now you have three projects:

Classical AjGenesis code generation, implemented in .NET (see examples folder)
AjGenesis in Javascript/Node, with SimpleTpl template engine, with interpolated Javascript expressions, and embedded Javascript commands (see samples folder)
AjGenesis in Ruby, with a similar internal template engine, with interpolated Ruby expressions, and embedded Ruby commands (see samples folder)

AjGenesis in Javascript was published to npm (node package manager) as beta.

AjGenesis in Ruby is still not a gem: work in progress.

REMEMBER: all these projects GENERATES the text artifacts YOU WANT to generate. There are not limited to a technology, platform or programming languages.

It’s really interesting to see how simple ideas can be reimplemented in dynamic languages. Next steps: more samples, ruby gem, node package, and web site implementing code generation as a service (ASP.NET implementation commented in my old post). (see AjGenesis: Basis of Its Implementation).

Pending implementation languages: Python, maybe Java.

(Original photo from: http://commons.wikimedia.org/wiki/File:Table_Rock_Dam_during_April_2008_White_River_Flood.jpg)

Keep tuned!

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

November 18, 2011

AjGenesis: Basis of its Implementation

Filed under: AjGenesis, Code Generation, Ruby — ajlopez @ 12:07 pm

I dedicated a lot of time to the development of AjGenesis, my open source code generation engine (from a free model). It’s time to write down what I consider the key points of its implementation, the parts that makes AjGenesis what it is.

First: the use of a free model on memory, that it’s managed like a common object in a programming language. You don’t need to traverse XML path or something else. You can visit and manipulated one or mode models  like any other dynamic object. I didn’t adopt a type model or a model with a schema: the model is free, you can put on each model what you want to have in it. The model is deserialized from XML or from text files, or it could be injected for your program: AjGenesis can be hosted as a library in your own application.

Second: the use of a dynamic, simple language, to execute simple or complex task, with access to rich class library. In AjGenesis, I use AjBasic, a interpreter that can access .NET. It can use, create and change dynamic objects, like the models.

Third: the use of templates, with expressions and commands (i.e. loops) written using the dynamic language.

(Some early alternatives were: use XML with schemas for models, and XSLT for transformations. I rejected them because I felt they had shortcomings that could affect the clear development of the system).

See:
Building an Application with AjGenesis
Code Generation with AjGenesis in a Real Project
Models for Code Generation in AjGenesis
AjBasic: An Open Source Basic-alike Interpreter
Generating Code Hello World with AjGenesis

Having these three pillars, I used AjGenesis for years, in different technologies, languages and framework (from Java to .NET, from JSP to ASP.NET to ASP.NET MVC, from PHP4 to PHP5 to .NET4 to .NET5, DDL for MySql, MS SQL Server database, and one user is generating code for Ruby and Rails!). Notably, I’m generating text artifacts for technologies that didn’t exist at the beginning of the project, with minimal changes to AjGenesis itself. And it can run in Linux and Mac OSX thanks to the Mono project (see Running AjGenesis Using Mono and Ubuntu).

Ideas to implement: the ability of inject the source of the model (you could write your own serializer); you could choose the dynamic language to use (I plan to add AjSharp as dynamic language for tasks and templates).

But if I have the three key points I enumerated above, I could implement AjGenesis. Then, as a proof of concept, I started to implement the same ideas under Ruby: dynamic objects, that can be loaded from YAML (or XML, or other formats), the use of ruby for task programming, and its template using ERB (or, maybe, other template engines).

You can check my progress at: https://github.com/ajlopez/AjGenesisRb

Keep tuned!

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

June 3, 2011

Raise the Level of Abstraction (Part 1) Introduction

Filed under: AjGenesis, Code Generation, Software Development — ajlopez @ 10:14 am

This century I wrote many posts about Code Generation. It’s a topic interested me since the eighties: how to make programs that write programs. But it’s not only code generation: it’s code generation from a model. That’s the key point to emphasize. Now, I want to write about the basis of such pragmatic solution to some of the problems in software development. My main assertion:

Code Generation From Model is an exercise of Raise the Level of Abstraction

The history of programming is a history of “raising the level of abstraction”. Instead to manipulate switch in the front panel of the first computers, we write programs using a language that is an abstraction: we use “int a”, as an abstraction of a word in memory. We write “foo(bar)” as an abstraction of save state in a stack, and jump to a memory address: we don’t write BALR (Branch and Link Register) instructions in IBM mainframe assembly language. Every day we use code generation: from the general/specific domain language our compilers generate the machine code, the only code that counts for our computers.

In this new post series I want to explore and write about these ideas:

– We improve our ideas and skills, but the technology is in constant change
– Abstract Model vs. Technology Models
– Separate problem from solutions
– Distill and reuse the developer knowledge
– Code generation FROM A MODEL as an exercise of abstraction
– Then, code generation from a model has a beneficial side-effect: shed light on the separation of what is important, from what is a technicality
– Code generation can (and must) coexist with human coding

Many of these topics were mentioned in my AjGenesis posts, but it’s time to present them as a integrated whole. The title of this post series “Raise the Level of Abstraction” was born in a technical talk at one of my customers, years ago. It’s good to find the same phrase as a “leit motiv” for Code Generation 2011:

http://www.codegeneration.net/cg2011/index.php

I remember an older phrase from the same site: “code generation for the pragmatic engineer”. Code generation from a model is not a silver bullet: is another bullet, you can use in the right context.

(Note: I found the images at top using Google Image search terms: “two apples”, “two oranges”, “two sheep” and…..  “two person” ;-)… no Microsoft promotion intended)

Keep tuned!

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

May 25, 2011

Code Generation and Artificial Intelligence

In late seventies and early eighties (past century ;-)) I was learning a lot about programming, programming languages and computer science in general. They were the days of COBOL, BCPL, IBM/360 assembler languages, JCL, punched cards, Pick Operating Systems, Pick Basic, ALGOL/W, Fortran, PL/I, and C (in CP/M, DOS, Unix/Xenix world). One of my preferred topics (then and now) was Artificial Intelligence, a broad term. Those days were the golden age of expert systems. I was writing a lot of C code, then, as a lazy programmer, I started to write my own C utilities to generate more C programs ;-). Since then, I have an idea:

Code Generation should be an Artificial Intelligence application

In the late eighties, early nineties, the amount of code to write to have a professional application diminished (new IDEs, wizards). But that was a transitory state: the complexity imposed by market, new customer requirements, online application, concurrency, new technologies and languages (Windows, GUIs…) all conspired to the increase of effort that should be employed to create any non-trivial application. I embraced Java at mid-90s, and .NET at 2001. Large class libraries, new tips and tricks, architectural styles, patterns, JSP, JSF, MVC, ASP.NET, Javascript, some PHP, distributed computing, physical tiers… The software development arena became more complex. And now, we have mobile, Android, Windows Phone 7, ASP.NET MVC, new JDKs, JVMs, new dynamic languages… I could continue this enumeration for ever, no break here ;-)

So, at the begin of the century, I decided to start my open source project for code generation, AjGenesis. First, this is the current process I use in my code generation projects:

(Ok, I’m a developer, not a designer ;-))

The staring models (left) are free: you can use any model you want, it’s not fixed. This is a key decision: I want YOU have the freedom to start whit whatever you want as a base for your code generation. But it should be a MODEL. It’s not only code generation: it’s CODE GENERATION FROM A MODEL(S). Usually, I have an abstract model, like:

<Project>
	<Name>AjApp</Name>
	<Description>Building an Application using AjGenesis</Description>
	<Model>
		<Entities>
			<Entity Source="Entities/Customer.xml"/>
			<Entity Source="Entities/Supplier.xml"/>
		</Entities>
	</Model>
</Project>

and one or more technology model, like:

<Technology>
	<Programming>
		<Dialect>CSharp4NhMvc</Dialect>
	</Programming>
	<Database>
		<Dialect>MsSql</Dialect>
		<Name>AjTestNh</Name>
		<Host>.\SQLEXPRESS</Host>
	</Database>
	<NHibernate>
		<Dialect>NHibernate.Dialect.MsSql2000Dialect</Dialect>
	</NHibernate>
</Technology>

(more info in my AjGenesis posts). The models can be written using XML or text. Or you can use your own models (see Models for Code Generation in AjGenesis). The text artifacts could be Java, C#, VB.NET, Ruby, whatever you want. Notably: my AjGenesis examples started generating PHP, and JSP 1.x, and they evolved WITHOUT CHANGING THE TOOL to generate PHP (new versions), Java, JSP 2.x, Hibernate, NHibernate, ASP.NET 1.x, ASP.NET 2.x, ASP.NET MVC… It can be adapted to any text-based technology. To have such flexibility, it has no GUI IDE association. It’s has Spartan interface, but I liked it.

Since inception, I adopted a general dynamic language, AjBasic, to support tasks and templates: I didn’t want a transformation engine, from model to code via templates. I want to have the power of a GENERAL language. Why? TO SUPPORT EXTENSIBILITY, beyond template expansion. And, surprise! What kind of extensibility? Anyone, but you know…. yes, right! Artificial Intelligence!

My assertion:

Code Generation from a Model can be implemented as an Expert System, and then, it’s a clear target for Artificial Intelligence

Graphically:

You can view software developers as experts. We can distill their expertise in expert systems and add them to code generation process. Some examples:

– An expert system can use a rule engine to make decisions: macro or mini ones. Mini-one: “This web report can have lot of rows, I need pagination, filtering, and ordering….” And then, some part of the expert systems recommends: “Yes! We could use JQuery and JQuery.UI, client-side filtering”… and other part (yes, my expert systems is multi-mind ;-)) says “No! We need server-side filtering, then we need such queries and services, and Ajax endpoints and … “ Got the picture?

A micro-decision I employed last year in a real project: one kind of entity, in an abstract model, was marked as “massive” meaning: “we have lot of instances of Entity X”. Then, when in the UI we needed to select one Entity X, instead of a dropdown, the code generation engine put a search box, with auto-complete, with Ajax service at server.

I could use, for the abstract model, some base ontology and make assumptions and decisions. Example:

– Every entity could be: a person, a company, a place, a physical good, an event, a document. Then, the expert system could infer: a place has an address. A physical good should be located in a place. A document X should be needed to represent the move of a physical good from place A to place B. A person can be an employee. Every employee has social security… etc…. etc.. Then, we need a report of the X events, ordered by date, grouped by location, etc… etc… This document has a money total, it should be interesting to have a total grouped by any party (customer? company? person?) involved in the document. And by month? Yes, we need a pie chart … and so on… ;-)

I could add a rule engine, to make some of these kind of decisions, with rules like “if entity X is massive and the UI is web and JQuery is an available option then … “. Or rules like: “if entity X inherits from entity Y and we need persistence, we adopt table-per-hierarchy (or table-per-concrete class) ORM strategy, and then we generate…. database tables and …. ORM mapping code or configuration”. Or: “this entity X is a document having a date, we add an index on that date/time column in Y table”. So many decisions can be made in this way. Actually, in AjGenesis, most of these decisions are in the tasks and technology models.

In the long term, code generation from a model involves:

– This is the starting point: abstract models, technical models (restrictions: “we need all this in ASP.NET MVC 3”)

– This is the expected deliverable (a partial working system)

– And these are the distilled expert knowledge we got from our/others experience.  And with all these, we can go from start to end. using the accumulated programming skills, ORM configuration, dependency injection libraries, UI tips and tricks, recurrent patterns, database creation knowledge, etc..

Software development and architecture is related to:

– Know what you need

– Know what are the problems to resolve (persistence, concurrency, security, traceability, UI access, etc…)

– Know what are the available solutions (database, NoSql, language, class libraries, frameworks, UI technology, patterns…)

Code generation from a model has a (great, IMO) benefit: it put clear the existence, separation and relations of the above points.

Other way to explore: the use of expert agents. What does “expert agent” mean in my jargon? My vision: you can have modules, agents that can be added, removed without much effort, that can resolves problems. Then, someone can develop a JSF expert, that knows what JavaBeans to define for implement a given interface in a use case. Then, if in the future the rule engine or the initial restrictions say: “Now, we need JSF 17.2, or ASP.NET MVC 6.5 or the new SuperDuperOpenSourceUIThatIsTheNextBigThingHere”, we can adopt new solutions for the similar problems, distilling the new knowledge and putting it in a new expert agent.

Ok, all these are the reasons for an (upcoming?) AjRules ;-). And the justification for AjLisp (see here) and some AjProlog to be updated (see it inside AjCodeKatas).

Related posts (in Spanish):

Models, decisions, Artificial Intelligence and AjGenesis

About Code Generation

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

March 14, 2011

More Language Workbench Competition 2011 with AjGenesis

Filed under: AjGenesis, Code Generation, Lwc2011 — ajlopez @ 9:03 am

In my previous post I described my initial work for Language Workbench Competition 2011, using AjGenesis. Now, it’s time to write about some new tasks I wrote. You can read the tasks of the competition at:

http://www.languageworkbenches.net/LWCTask-1.0.pdf

First, I skipped Phase 0.3 (constraint checks such as name-uniqueness). I plan to complete it, but not now. I wrote Phase 0.4:

0.4 Show how to break down a (large) model into several parts, while still cross-referencing between the parts. For example, put the Car and Person entities into different files, while still having the Person -> Car reference work.

The code was committed to AjGenesis repository:

http://ajgenesis.codeplex.com/SourceControl/list/changesets

under examples/Lcw2011

This step was an easy one. The Project.txt is:

Project Lwc2011
	Entities
		Entity Person Source="Entities\Person.txt"	
		Entity Car Source="Entities\Car.txt"
	End Entities
End Project

 

The Source attribute is special in AjGenesis model loading: it indicates a separate file to load in order to complete the object. I added this feature in the early times of AjGenesis: I want to have model files that are manageable, that don’t hurt the eyes ;-)

This is Person.txt:

Entity Person
	Properties
		Property Name Type="Text"
		Property FirstName Type="Text"
		Property BirthDate Type="Date"
		Property OwnedCar Type="Car"
	End Properties
End Entity

I began to write Phase 1.0 first step:

1.1 Show the integration of several languages. Define a second language to define instances of the entities, including assignment of values to the properties. This should ideally really be a second language that integrates with the first one, not just "more syntax" in the same

grammar. We want to showcase language modularity and composition here.

This is the new model:

Project Lwc2011
	Description = "Lwc"
	Entities
		Entity Person Source="Entities\Person.txt"	
		Entity Car Source="Entities\Car.txt"
	End Entities
	
	Instances
		Instance p 
			Type = "Person"
			Properties
				Property Name Value = "Voelter"
				Property FirstName Value = "Markus"
				Property BirthDay Value = "14/02/1927"
				Property OwnedCar Value = "c"
			End Properties
		End Instance
		
		Instance c 
			Type = "Car"
			Properties
				Property Make Value = "VW"
				Property Model Value = "Touran"
			End Properties
		End Instance
	End Instances
End Project

But it’s still work in progress. I could put the instances in another independent model file (Instances.txt) or I could put the each instance in a separate file, referenced by the above one using Source attribute. I should complete the tasks checking the existence of each property in the entity type that correspond to each instance. AjGenesis doesn’t support Domain-Specific Language definition: the above example is still a free model. You can add any property to any instance, and the current implementation doesn’t check the proper use of the model. So, this kind of check is pending work: I will add the checking logic in the tasks to execute.

Apparently, this task doesn’t involve code generation. In the next task, I should check the values of the properties, too.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

March 8, 2011

AjGenesis and Language Workbench Competition 2011

Filed under: AjGenesis, Code Generation, Lwc2011 — ajlopez @ 5:33 pm

Last week, thanks to a @pmolinam, I met

Language Workbench Competition 2011

Molina had sent me the info last year, but I forget the challenge. It is mentioned in InfoQ:

Language Workbench Competition 2011 Submissions

You can read the task list at:

http://www.languageworkbenches.net/LWCTask-1.0.pdf

I don’t sure if AjGenesis could qualify as a Language Workbench: it’s more oriented to be a free-model code generation tool. It has no IDE integration, but it is flexible and language-independent. It doesn’t produce any DSL: instead, it has a free model that can be use in many ways, to describe the concepts you have to model, without attached domain specific language. @pmolinam asked if I could complete the tasks using AjGenesis, my open source codegeneration tool. My answer: Yes!

Then, some messages appeared at twitter:

Today, I started to write Phase 0, points 0.1-0.2. The example is at AjGenesis trunk, at:

http://ajgenesis.codeplex.com/SourceControl/list/changesets

under examples/Lcw2011

The first point 0.1 is:

0.1 Simple (structural) DSL without any fancy expression language or such. Build a simple data definition language to define entities with properties. Properties have a name and a type. It should be possible to use primitive types for properties, as well as other Entities.

entity Person { 
    string name
    string firstname
    date bithdate
    Car ownedCar
}


entity Car { 
    string make
    string model
}

I wrote a simple Project.txt (note that I’m using the textual model instead the XML one, see Models for AjGenesis and Textual model for Code Generation in AjGenesis ).

Project Lwc2011
    Entities
	Entity Person
	    Properties
		Property Name Type="Text"
		Property FirstName Type="Text"
		Property BirthDate Type="Date"
		Property OwnedCar Type="Car"
	    End Properties
	End Entity
	
	Entity Car
	    Properties
		Property Make Type="Text"
		Property Model Type="Text"
	    End Properties
	End Entity
    End Entities
End Project

The Phase 0-0.2:

0.2 Code generation to GPL such as Java, C#, C++ or XML Generate Java Beans (or some equivalent data structure in C#, Scala, etc.) with setters, getters and fields for the properties.

Using assets from my post Building An Application using AjGenesis (Part 4), I wrote the commands:

GenerateCSharp.cmd

GenerateJava.cmd

GenerateVbNet.cmd

I’m using additional model files for describing technology. This is my VbNet technology model:

<Technology>
	<Name>VbNet</Name>
</Technology>

Simple! This time, I’m using the XML model (in memory, textual and XML have the same features; it’s only a serialization option).

Look at GenerateCSharp.cmd:

AjGenesis.Console Project\Project.txt Project\Technologies\CSharp.xml Tasks\Complete.ajg Tasks\Generate.ajg

It loads the Project.txt, the corresponding technology model, loads and executes the Complete.ajg task, and then loads and executes the Generate.ajg task. The Complete.task (see the mentioned post Building An Application using AjGenesis (Part 4)) it’s used for complete the model: one thing it dows is to translate abstract types like “Text”, to the corresponding final language type, like “string” in C#, or “String” in Java.

The Generate.ajg takes the enriched model and generate the code for each entity, using templates. This is the template for C#:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace ${Project.CSharp.Namespace} {
	public class ${Entity.Name}
	{
<#
	for each Property in Entity.Properties
#>
		public ${Property.CSharp.Type} ${Property.Name} { get; set; }
<#
	end for
#>
	}
}

The generated code for Person entity:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace Lwc2011 {
	public class Person
	{
		public string Name { get; set; }
		public string FirstName { get; set; }
		public DateTime BirthDate { get; set; }
		public Car OwnedCar { get; set; }
	}
}

Next steps: complete 0.3, 0.4 tasks, and then, solve Phase 1. I could complete the assignment in two weeks. I will publish the advance in upcoming posts.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

October 9, 2010

Running AjGenesis using Mono and Ubuntu

Filed under: .NET, AjGenesis, Code Generation, Mono, Ubuntu — ajlopez @ 8:52 am

In these days, I am involved in the developing of a new version (complete rewriting) of a Java application, with a web interface. It is a team effort, and the majority of the members are Ubuntu fans: there are more proficient working in Linux boxes. The project has code generation using (make an educated guess.. ;-) AjGenesis, my open source code generation project. Then, the team want to run AjGenesis out of Windows.

AjGenesis is written in VB.NET, and compiled for .NET 2.0. I was afraid that I should make some change to run it under Ubuntu using Mono project. But I was wrong. Ubuntu has  Mono pre-installed. But AjGenesis use VB.NET runtime. Well, Mono has a VB.NET compiler. I launched the terminal in my Ubuntu ( in Virtual Box over Windows 2008), and executed:

sudo apt-get install mono-vbnc

(I guess this step is needed, but I didn’t try to run AjGenesis with only Mono installed).

Then, I downloaded the AjGenesis compiled binaries (from source trunk). And some examples, like AppExampleStep06.zip (described in Building an Application using AjGenesis (Part 6)).

You can run AjGenesis.Console.exe using

mono AjGenesis.Console.exe

But I marked it as executable:

chmod +xr- AjGenesis.Console.exe

so you can run it directly:

The Build folder was created! Nice!

After this first experiment, I got the source code of the project using subversion, and run the code generation script. The only gotchats were some tasks, written in AjBasic, that were creating directories in lower case and using them with one upper case letter. I fixed the bug, and now, the code generation is running. Team members are able to develop in Windows and Ubuntu, using Java, Tomcat, Maven, and AjGenesis.

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

October 4, 2010

Building an Application using AjGenesis (Part 6)

Filed under: AjGenesis, Code Generation, Open Source Projects — ajlopez @ 9:51 am

In the previous post in this series, I added a lot of stuff to manage the generation of .NET projects and solutions. That files are complicated. In contrast, to generate something alike for Java, I only need to generate the folder structure for package, and maybe add Ant or Maven files. But in .NET, I was to struggle with the structure of solution and project files. The code for this part can be downloaded from AppExampleStep06.zip. You need the compiled binaries AjGenesisTrunkBinaries.zip. The complete AjGenesis project, including the examples for this post series, can be downloaded from http://ajgenesis.codeplex.com.

One of the complicated part was to add all .cs and .vb files inside the project file. I wrote:

for each Entity in Project.Model.Entities
  TransformerManager.Transform("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Project.Name}.Entities/${Entity.Name}.cs", Environment)
  PrjEntities.Includes.Add(CreateFileCs("${Entity.Name}"))
end for

The Includes list in PrjEntities object keeps the information of the files to add in the project file generation. Instead of adding the files in that way, now I add ALL .cs files in the C# project, and all .vb files in the VB.Net project. So, you can add your own custom files, and the project files still will reference them after regeneration of the solution. The key code is inside the Utilities/DotNetUtilities.ajg:

Sub AddVbFilesToProject(project)
  di = new System.IO.DirectoryInfo(project.Directory)
  prefix = ""
  AddVbFiles(project, name, di)
End Sub
Sub AddVbFiles(project, prefix, di)
  for each fi in di.GetFiles("*.vb")
    name = fi.Name.Substring(0, fi.Name.Length - 3)
    project.Includes.Add(CreateFileVb(prefix & name))
  end for
  
  sdirs = di.GetDirectories()
  
  for each sdir in sdirs
    AddVbFiles(project, prefix & sdir.Name & "\", sdir)
  end for
End Sub
Sub AddCsFilesToProject(project)
  di = new System.IO.DirectoryInfo(project.Directory)
  prefix = ""
  AddCsFiles(project, name, di)
End Sub
Sub AddCsFiles(project, prefix, di)
  for each fi in di.GetFiles("*.cs")
    name = fi.Name.Substring(0, fi.Name.Length - 3)
    project.Includes.Add(CreateFileCs(prefix & name))
  end for
  
  sdirs = di.GetDirectories()
  
  for each sdir in sdirs
    AddCsFiles(project, prefix & sdir.Name & "\", sdir)
  end for
End Sub

Another feature I added in this step: in the previous post, each time the generation was launched, it created all the files again. Now, it use a new routine, included in Utilities/TransformUtilities.ajg:

Sub TransformFile(tpl, target, tm, env)
  if System.IO.File.Exists(target) then
    target2 = target & ".tmp"
    tm.Transform(tpl, target2, env)
    content1 = System.IO.File.ReadAllText(target)
    content2 = System.IO.File.ReadAllText(target2)
    if content1 <> content2 then
      System.IO.File.Copy(target2, target, true)
    end if
    System.IO.File.Delete(target2)
  else
    tm.Transform(tpl, target, env)
  end if
End Sub

Now, instead of invoking the predefined object TransformerManager:

  TransformerManager.Transform("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Project.Name}.Entities/${Entity.Name}.cs", Environment)

the task invoke the new routine, that compares the new file with the old one, and replace it only if they are different:

  TransformFile("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Project.Name}.Entities/${Entity.Name}.cs", TransformerManager, Environment)

Next steps, for future posts: include identity to entities in model, generate database creation DLLs, DAOs, and some Java code.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

September 13, 2010

Building an Application Using AjGenesis (Part 5)

Filed under: AjGenesis, Code Generation, Open Source Projects — ajlopez @ 9:06 am

I just published a new step in this post series. The code can be downloaded from AppExampleStep05. The example:

At root folder, the example have the same three commands, as in the previous post.

GenerateCSharp.cmd
GenerateJava.cmd
GenerateVbNet.cmd

The model is the same. But I wrote new Tasks/GenerateCSharp.ajg, Tasks/GenerateVbNet.ajg. Now, you can generate a .NET solution and project. This is the GenerateCSharp.ajg:

IncludeCode "Utilities/Utilities.ajg"
IncludeCode "Utilities/DotNetUtilities.ajg"
' Create Build Directories
FileManager.CreateDirectory(Project.BuildDirectory)
FileManager.CreateDirectory("${Project.BuildDirectory}")
FileManager.CreateDirectory("${Project.BuildDirectory}/${Project.Name}.Entities")
FileManager.CreateDirectory("${Project.BuildDirectory}/${Project.Name}.Entities/Properties")
Project.Solution = CreateObject()
Project.Solution.Guid = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"
Project.Solution.WebGuid = "E24C65DC-7377-472B-9ABA-BC803B73C61A"
Project.Solution.Projects = CreateList()
PrjEntities = CreateObject()
PrjEntities.Name = "${Project.Name}.Entities"
PrjEntities.Directory = "${Project.BuildDirectory}/${Project.Name}.Entities"
PrjEntities.Includes = CreateList()
PrjEntities.Projects = CreateList()
PrjEntities.Libraries = CreateList()
PrjEntities.Guid = CreateGuid()
PrjEntities.COMGuid = CreateGuid()
Project.Solution.Projects.Add(PrjEntities)
for each Entity in Project.Model.Entities
  TransformerManager.Transform("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Project.Name}.Entities/${Entity.Name}.cs", Environment)
  PrjEntities.Includes.Add(CreateFileCs("${Entity.Name}"))
end for
for each CsProject in Project.Solution.Projects
  TransformerManager.Transform("Templates/CSharp/CsProject.tpl", "${CsProject.Directory}/${CsProject.Name}.csproj", Environment)
  TransformerManager.Transform("Templates/CSharp/AssemblyInfoCs.tpl", "${CsProject.Directory}/Properties/AssemblyInfo.cs", Environment)
end for
TransformerManager.Transform("Templates/CSharp/Solution.tpl", "${Project.BuildDirectory}/${Project.Name}.sln", Environment)

Lot of new things! But the point is: now, I generate a solution file, and a project file. There are new files with utilities, and new templates. Note the creation of Project.Solution dynamic object, and PrjEntities.

The solution generated in C#:

A solution and project is generate for Vb.NET, too:

Next steps: don’t generate again files that not changed since last time;’ able to have manual code in projects and keep them; new projects (persistence, web interface, …)

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

July 14, 2010

Building an Application Using AjGenesis (Part 4)

Filed under: AjGenesis, Code Generation, Open Source Projects — ajlopez @ 7:28 pm

In this post, I will generate, from the same model, text files for C#, Java, and VB.NET. Previous posts:

Building An Application Using AjGenesis (Part 1)
Building An Application Using AjGenesis (Part 2)
Building an Application Using AjGenesis (Part 3)

The code of this post can be downloaded from AppExampleStep04.zip.

You need the latest AjGenesis binaries. You can get them from AjGenesisTrunkBinaries.zip. (the full source code is at AjGenesis Codeplex repository). You should add the bin directory to your path, to run the examples of this post.

The example now has more folder structure:

Projects\AjApp is the folder containing the model of the example, in Project.xml:

<Project>
	<Name>AjApp</Name>
	<Description>Building an Application using AjGenesis</Description>
	<Model>
		<Entities>
			<Entity Source="Entities/Customer.xml"/>
			<Entity Source="Entities/Supplier.xml"/>
		</Entities>
	</Model>
</Project>

I could add more folders, describing other projects, if needed.

At root folder, the example have three commands:

GenerateCSharp.cmd

GenerateJava.cmd

GenerateVbNet.cmd

The three commands have a similar content. This is the GenerateCSharp.cmd:

AjGenesis.Console Projects\AjApp\Project.xml Projects\AjApp\Technologies\CSharp.xml Tasks\Complete.ajg Tasks\Generate.ajg

Note there is two model: Project.xml is like the previous posts. The new one describe the technology to use, CSharp.xml:

<Technology>
	<Name>CSharp</Name>
</Technology>

Now, it’s only the name of the programming language. I could extend this model to define database, web servers to use, etc…. Then: Project.xml is the abstract model. Technologies\CSharp.xml, Technologies\VbNet.xml, Technologies\Java.xml are the models describing the technology to use. Each of the Generate*.cmd loads the abstract model, AND one of the tech ones.

The Complete.ajg:

' Set Build Directory
if not Project.BuildDirectory then
	Project.BuildDirectory = "Build/${Project.Name}/${Technology.Name}"
end if
FileManager.CreateDirectory(Project.BuildDirectory)
IncludeCode "Tasks/Complete${Technology.Name}.ajg"

Note the use of a trick: include the code of another file, to run, using a dynamic string. If Technology.Name == “CSharp”, the above task will execute CompleteCSharp.ajg:

' Some functions
' Name to use for variables
function CSharpVariableName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToLower() & name.Substring(1)
end function
' Name to use for Classes, Properties..
function CSharpName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToUpper() & name.Substring(1)
end function
function CSharpType(type)
	type = type.ToLower()
	
	if type="text" then
		return "string"
	end if
	
	if type="integer" then
		return "int"
	end if
	
	return type
end function
' Set namespace to use in CSharp code
if not Project.CSharp.Namespace then
	Project.CSharp.Namespace = CSharpName(Project.Name)
end if
' Complete Entities
for each Entity in Project.Model.Entities
	' Set the variable name to use for an entity
	if not Entity.CSharp.VariableName then
		Entity.CSharp.VariableName = CSharpVariableName(Entity.Name)
	end if
	
	for each Property in Entity.Properties
		' Set the CSharp to use in each property
		if not Property.CSharp.Type then
			Property.CSharp.Type = CSharpType(Property.Type)
		end if
	end for
end for

There are similar tasks for the others technologies: CompleteVbNet.ajg, CompleteJava.ajg. These tasks complete the model in memory (like assigning namespaces, packages, variable names to properties, build directory…)

The second task is Generate.ajg:

IncludeCode "Tasks/Generate${Technology.Name}.ajg"

Again, the old trick of dynamic include. This is the GenerateCSharp.ajg subtask:

for each Entity in Project.Model.Entities
	TransformerManager.Transform("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Entity.Name}.cs", Environment)
end for

To compare, this is the CompleteJava.ajg:

' Some functions
' Name to use for variables
function JavaVariableName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToLower() & name.Substring(1)
end function
' Name to use for Classes, Properties..
function JavaName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToUpper() & name.Substring(1)
end function
function JavaType(type)
	type = type.ToLower()
	
	if type="text" then
		return "String"
	end if
	
	if type="integer" then
		return "int"
	end if
	
	return type
end function
' Set package to use in Java code
if not Project.Java.Package then
	Project.Java.Package = JavaName(Project.Name).ToLower()
end if
' Complete Entities
for each Entity in Project.Model.Entities
	' Set the variable name to use for an entity
	if not Entity.Java.VariableName then
		Entity.Java.VariableName = JavaVariableName(Entity.Name)
	end if
	
	for each Property in Entity.Properties
		if not Property.Java.VariableName then
			Property.Java.VariableName = JavaVariableName(Property.Name)
		end if
		
		' Set the Java to use in each property
		if not Property.Java.Type then
			Property.Java.Type = JavaType(Property.Type)
		end if
	end for
end for

and the GenerateJava.ajg:

for each Entity in Project.Model.Entities
	TransformerManager.Transform("Templates/Java/EntityClass.tpl", "${Project.BuildDirectory}/${Entity.Name}.java", Environment)
end for

There are templates for each technology. This is EntityClass.tpl for CSharp:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace ${Project.CSharp.Namespace} {
	public class ${Entity.Name}
	{
<#
	for each Property in Entity.Properties
#>
		public ${Property.CSharp.Type} ${Property.Name} { get; set; }
<#
	end for
#>
	}
}

and this is EntityClass.tpl for Java:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
package ${Project.Java.Package};
public class ${Entity.Name}
{
<#
	for each Property in Entity.Properties
#>
		private ${Property.Java.Type} ${Property.Java.VariableName};
<#
	end for
	for each Property in Entity.Properties
#>
		public ${Property.Java.Type} get${Property.Name}()
		{
			return this.${Property.Java.VariableName};
		}
		public void set${Property.Name}(${Property.Java.Type} value)
		{
			this.${Property.Java.VariableName} = value;
		}
<#
	end for
#>
}

Running the three Generate*.cmds, create the Build folder, with Build\AjApp, Build\AjApp\CSharp, Build\AjApp\Java, Build\AjApp\VbNet subfolders.

The generated Customer.cs:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace AjApp {
	public class Customer
	{
		public string Name { get; set; }
		public string Address { get; set; }
	}
}

The generated Customer.vb:

' Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
Namespace AjApp
	Public Class Customer
		Private mName as String
		Private mAddress as String
		Public Property Name as String
			Get
				return Me.mName
			End Get
			Set(value as String)
				Me.mName = value
			End Value
		End Property		
		Public Property Address as String
			Get
				return Me.mAddress
			End Get
			Set(value as String)
				Me.mAddress = value
			End Value
		End Property		
	End Class
End Namespace

The generated Customer.java:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
package ajapp;
public class Customer
{
		private String name;
		private String address;
		public String getName()
		{
			return this.name;
		}
		public void setName(String value)
		{
			this.name = value;
		}
		public String getAddress()
		{
			return this.address;
		}
		public void setAddress(String value)
		{
			this.address = value;
		}
}

Next steps: to generate a C# or VB.NET project, to load in Visual Studio, or an Eclipse project for Java.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

« Newer PostsOlder Posts »

The Shocking Blue Green Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 68 other followers