En este post, generaremos, desde el mismo modelo, archivos de texto para C#, Java, y VB.NET. Anteriores post:
Building An Application Using AjGenesis (Part 1)
Armando una Aplicación usando AjGenesis (Parte 1)
Building An Application Using AjGenesis (Part 2)
Armando una Aplicación usando AjGenesis (Parte 2)
Building an Application Using AjGenesis (Part 3)
Armando una Aplicación usando AjGenesis (Parte 3)
El código de este post puede bajarse desde AppExampleStep04.zip.
Necesitamos los binarios últimos de AjGenesis. Podemos bajarlo desde AjGenesisTrunkBinaries.zip. (el código fuente completo está en el repositorio de AjGenesis en Codeplex). Tienen que agregar el directorio bin al path, para ejecutar los ejemplos de este post.
El ejemplo ahora tiene más estructura:
Projects\AjApp es el folder conteniendo el modelo del ejemplo, en 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>
Podría, entonces, agregar más carpetas, con otros proyectos, si lo necesitara.
En el directorio inicial, tenemos tres comandos:
GenerateCSharp.cmd
GenerateJava.cmd
GenerateVbNet.cmd
Los tres comandos tienen un contenido similar. Por ejemplo, veamos el de GenerateCSharp.cmd:
AjGenesis.Console Projects\AjApp\Project.xml Projects\AjApp\Technologies\CSharp.xml Tasks\Complete.ajg Tasks\Generate.ajg
Notemos que hay dos modelos que se cargan en modelo: Project.xml es como en los anteriores posts, tiene el modelo independiente de la tecnología. El nuevo, CSharp.xml, describe la tecnología a usar:
<Technology>
<Name>CSharp</Name>
</Technology>
Por ahora, contiene solo el nombre del lenguaje a usar. Podría extender este modelo, en próximos posts, para que contenga la base de datos a usar, el webserver a usar, etc… Entonces: Project.xml es el modelo abstracto. Technologies\CSharp.xml, Technologies\VbNet.xml, Technologies\Java.xml son los modelos que describen la tecnología a usar. Cada uno de los comandos Generate*.cmd carga el modelo abstracto, Y uno de los tecnológicos.
La tarea 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"
Noten el uso de un nuevo truco: incluir el código a ejecutar desde otro archivo, usando un string dinámico. Si Technology.Name == “CSharp”, la tarea de arriba termina ejecutando 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
Hay tareas escritas similares a la de arriba, para otras tecnologías: CompleteVbNet.ajg, CompleteJava.ajg. Estas tareas completan el modelo en memoria (asignando namespaces, packages, nombres para usar en las variables y propiedaes, el directorio a usar para dejar lo generado, etc…)
La segunda tarea es Generate.ajg:
IncludeCode "Tasks/Generate${Technology.Name}.ajg"
De nuevo, el viejo truco de un include de código dinámico. Esta es la subtarea GenerateCSharp.ajg:
for each Entity in Project.Model.Entities
TransformerManager.Transform("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Entity.Name}.cs", Environment)
end for
Compare, con 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
y el GenerateJava.ajg:
for each Entity in Project.Model.Entities
TransformerManager.Transform("Templates/Java/EntityClass.tpl", "${Project.BuildDirectory}/${Entity.Name}.java", Environment)
end for
Hay templates para cada tecnología. Ejemplo, este es el EntityClass.tpl para 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
#>
}
}
y éste es el de Java EntityClass.tpl:
// 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
#>
}
Ejecutando los tres comandos Generate*.cmds, se crea el directorio Build, con Build\AjApp, Build\AjApp\CSharp, Build\AjApp\Java, Build\AjApp\VbNet, un directorio por el proyecto, con subdirectorios por tecnología.
Veamos el Customer.cs generado:
// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace AjApp {
public class Customer
{
public string Name { get; set; }
public string Address { get; set; }
}
}
El Customer.vb generado:
' 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
Y el Customer.java generado:
// 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;
}
}
Próximos pasos: generar proyectos C# o VB.NET, listos para cargar en Visual Studio, o un proyecto Eclipse para Java.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez